J'essaie de créer un nouveau composant, ResultComponent
, mais sa méthode ngOnInit()
est appelée deux fois et je ne sais pas pourquoi cela se produit. Dans le code, ResultComponent
hérite de @Input
du composant parent mcq-component
.
Voici le code:
Composant parent (MCQComponent)
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'mcq-component',
template: `
<div *ngIf = 'isQuestionView'>
.....
</div>
<result-comp *ngIf = '!isQuestionView' [answers] = 'ansArray'><result-comp>
`,
styles: [
`
....
`
],
providers: [AppService],
directives: [SelectableDirective, ResultComponent]
})
export class MCQComponent implements OnInit{
private ansArray:Array<any> = [];
....
constructor(private appService: AppService){}
....
}
Composant enfant (result-comp)
import { Component, OnInit, Input } from '@angular/core';
@Component({
selector:'result-comp',
template: `
<h2>Result page:</h2>
`
})
export class ResultComponent implements OnInit{
@Input('answers') ans:Array<any>;
ngOnInit(){
console.log('Ans array: '+this.ans);
}
}
Lorsqu'il est exécuté, console.log
apparaît deux fois, la première fois, il affiche le tableau correct, mais la deuxième fois, il donne undefined
. Je n'ai pas été capable de comprendre: pourquoi ngOnInit
dans ResultComponent
est-il appelé deux fois?
À l'heure actuelle, si une erreur survient lors de la détection des modifications des enfants de contenu/vue d'un composant, ngOnInit sera appelé deux fois (visible dans DynamicChangeDetector). Cela peut entraîner des erreurs de suivi qui cachent l'erreur d'origine.
Cette information provient de ceci numéro de github
Il semble donc que votre erreur pourrait avoir une origine ailleurs dans votre code, liée à ce composant.
Cela m'arrivait à cause d'un composant HTML défectueux. J'avais oublié de fermer la balise de sélection dans le composant Host. Alors j'ai eu ce <search><search>
, au lieu de <search></search>
- notez l'erreur de syntaxe.
Relativement lié à @dylan answer, vérifiez la structure html de votre composant et celle de son parent.
Eh bien, le problème dans mon cas était la façon dont je bootais les composants enfants. Dans mon @ NgModule objet de métadonnées du décorateur, je passais 'composant enfant' dans la propriété bootstap avec 'composant parent '. Le passage des composants enfants dans la propriété bootstap était réinitialisation mes composants enfants propriétés et rendant OnInit () déclenché deux fois.
@NgModule({
imports: [ BrowserModule,FormsModule ], // to use two-way data binding ‘FormsModule’
declarations: [ parentComponent,Child1,Child2], //all components
//bootstrap: [parentComponent,Child1,Child2] // will lead to errors in binding Inputs in Child components
bootstrap: [parentComponent] //use parent components only
})
si vous avez utilisé platformBrowserDynamic().bootstrapModule(AppModule);
dans app.module.ts, commentez-le et essayez. J'ai eu le même problème. Je pense que cela aide
Mettre ceci ici au cas où quelqu'un finirait par là. NgOnInit peut également être appelé deux fois si le type de bouton par défaut de votre navigateur est "submit". Par exemple, si vous avez le texte ci-dessous, NgOnInit de NextComponent sera appelé deux fois dans Chrome:
<button class="btn btn-primary" (click)="navigateToNextComponent()">
Pour résoudre ce problème, définissez le type:
<button class="btn btn-primary" type="button" (click)="navigateToNextComponent()">
Cela peut arriver parce que vous avez défini le AppComponent
comme itinéraire par défaut.
RouterModule.forRoot([
{ path: '', component: AppComponent } // remove it
])
Remarque: AppComponent
est appelé par défaut dans angular
alors vous n'avez pas besoin de l'appeler
La ngOnInit()
ne raccroche qu'une seule fois après l'instanciation de toutes les directives. Si vous avez un abonnement insidengOnInit()
et qu'il n'est pas désabonné, il s'exécutera à nouveau si les données souscrites changent.
Dans l'exemple suivant de Stackblitz, j'ai souscrit un abonnement dans ngOnInit()
et je console le résultat. Il console deux fois parce qu'il charge une fois et que les données changent et se chargent à nouveau.
Cela se produit chaque fois qu'il y a des erreurs de modèle.
Dans mon cas, j’utilisais un mauvais modèle de référence et je corrigeais le problème.
Cela m'est arrivé parce que j'avais non nommé <router-outlet>
s à l'intérieur d'un *ngFor
. Il a chargé pour chaque itération dans la boucle.
La solution, dans ce cas, consisterait à attribuer un nom unique à chaque sortie ou à s’assurer qu’il n’en existe qu’un dans le DOM à la fois (peut-être avec un *ngIf
).
Dans mon cas, cela se produit lorsque Component implémente à la fois OnChanges et OnInit. Essayez de supprimer l'une de ces classes. Vous pouvez également utiliser la méthode ngAfterViewInit, elle est déclenchée après l’initialisation de la vue, de sorte qu’elle soit garantie une fois appelée.
Pour moi, cela est dû au fait que j'ai enregistré le même composant deux fois dans Route:
{
path: 'meal-services',
children: [
{
path: '',
component: InitTwiceComponent,
canActivate: [AppVendorOpsGuard],
data: { roleWhitelist: [UserRoles.Manage] }
},
{
path: ':itemID',
component: InitTwiceComponent,
canActivate: [AppVendorOpsGuard],
data: { roleWhitelist: [UserRoles.Manage] }
}]
},
}
J'avais moi-même un problème similaire: je demandais un composant, puis je faisais référence au même composant via le routeur-prise.
<layout>
<router-outlet></router-outlet>
</layout>
Et la voie de sortie pointait également vers Layout.
Dans mon cas, je ne me suis pas désabonné de tous les abonnements que j'avais à l'intérieur de ngOnInit. Je viens désabonné de tous les abonnements au sein de ngOnDestroy et cela a résolu mon problème.