Cette erreur est similaire à l'erreur NG0500, mais elle signifie que le processus d'hydratation d'Angular attendait davantage de nœuds frères à un emplacement précis du DOM et ne les a pas trouvés. Consultez la page de l'erreur NG0500 pour les causes liées à la manipulation directe du DOM.
Une cause fréquente : du contenu conditionnel qui diffère entre le serveur et le client
En dehors de la manipulation directe du DOM, cette erreur survient souvent lorsque le contenu d'un @if ou d'un @for est rendu différemment sur le serveur et lors de l'hydratation côté client. Si le serveur a évalué une condition à true (ou rendu une liste avec plus d'éléments), mais que le client la voit à false (ou avec une liste plus courte) au moment de l'hydratation, le client finit par attendre moins de nœuds frères que le serveur n'en a réellement envoyé. L'hydratation échoue alors en parcourant les nœuds frères.
Un cas fréquent : une valeur provient d'un input(), mais au lieu d'utiliser cet input directement (ou via computed()), elle est copiée une seule fois dans un simple signal() à l'intérieur de ngOnInit() ou du constructeur :
@Component({
selector: 'app-example',
template: `
@if (visibleItems().length) {
<ul>
@for (item of visibleItems(); track item) {
<li>{{ item }}</li>
}
</ul>
}
`,
})
export class Example {
items = input<string[]>();
// This only runs once. If `items()` is not ready yet at the exact
// moment `ngOnInit` runs, this signal can end up holding a different
// value on the server than it does on the client. That means a
// different number of DOM nodes gets rendered on each side, which
// causes a hydration mismatch.
visibleItems = signal<string[]>([]);
ngOnInit() {
this.visibleItems.set(this.items() ?? []);
}
}
La solution consiste à dériver la valeur au lieu de la copier une seule fois. Ainsi, chaque rendu, y compris le tout premier, correspond toujours à l'input :
export class Example {
items = input<string[]>();
visibleItems = computed(() => this.items() ?? []);
}
Si vous devez aussi permettre aux utilisateurs de remplacer cette valeur localement, par exemple avec un bouton « afficher plus » qui révèle des éléments supplémentaires, utilisez linkedSignal() plutôt qu'un simple signal() défini depuis un lifecycle hook.
Déboguer l'erreur
Consultez l'erreur NG0500 pour des conseils sur le débogage des causes liées à la manipulation directe du DOM.
Cette erreur seule ne vous indique pas quel composant l'a provoquée. L'extension de navigateur Angular DevTools peut vous aider : elle peut mettre en évidence le composant exact où l'incohérence d'hydratation s'est produite. Une fois ce composant trouvé, examinez la façon dont il calcule chaque valeur utilisée dans un @if ou un @for de son template. Vérifiez si cette valeur provient directement d'un input() (via un binding de template ou computed()), ou si elle est copiée dans un signal à l'intérieur d'un lifecycle hook, comme illustré ci-dessus.