2017-09-06 8 views
3

を結合exampleです:ExpressionChangedAfterItHasBeenCheckedErrorはここ

エラーが時折現れる
@Component({ 
    selector: 'my-app', 
    template: ` 
    <div> 
     <h1>{{ foo }}</h1>  
     <bpp [(foo)]="foo"></bpp> 
    </div> 
    `, 
}) 
export class App { 
    foo; 
} 

@Component({ 
    selector: 'bpp', 
    template: ` 
    <div> 
     <h2>{{ foo }}</h2> 
    </div> 
    `, 
}) 
export class Bpp { 
    @Input('foo') foo; 

    @Output('fooChange') fooChange = new EventEmitter(); 

    ngAfterViewInit() { 
    const potentiallyButNotNecessarilyAsyncObservable = Observable.of(null); 

    potentiallyButNotNecessarilyAsyncObservable.subscribe(() => { 
     this.fooChange.emit('foo'); 
    }) 
    } 
} 

ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'undefined'. Current value: 'foo'

それは双方向結合が観察できること缶によって更新されたことに起因します同じ目盛りで値を得る。上記のロジックをsetTimeoutとラップしない方がよいでしょう。なぜなら、ハックのように見え、制御フローを複雑にするからです。

ここでこのエラーを回避するには何ができますか?

ExpressionChangedAfterItHasBeenCheckedErrorエラーは悪影響を及ぼすことがありますか無視できますか?可能であれば、検出器を静かにして、コンソールを汚染しないように変更できますか?

+0

エラーは発生しませんが、非同期パイプを使用しようとしましたか?それが助けになるかもしれません。 – fastAsTortoise

+0

@fastAsTortoiseここではパイプは使用できませんテンプレートに関係なくエラーが表示されます。 – estus

答えて

4

ましょう最初の説明を簡単にするために結合双方向のデータをアンラップ:

<div> 
    <h1>{{ foo }}</h1>  
    <bpp [foo]="foo" (fooChange)="foo=$event"></bpp> 
</div> 

それはまだ同じ効果があり、時折、エラーを生成します。エラーはpotentiallyButNotNecessarilyAsyncObservableが同期している場合にのみ生成されます。だから我々はまた、これを置き換えることができます。これに

ngAfterViewInit() { 
    const potentiallyButNotNecessarilyAsyncObservable = Observable.of(null); 

    potentiallyButNotNecessarilyAsyncObservable.subscribe(() => { 
     this.fooChange.emit('foo'); 
    }) 

を:

ngAfterViewInit() { 
    this.fooChange.emit('foo'); 

この場合は記事Everything you need to know about the ExpressionChangedAfterItHasBeenCheckedError errorで説明されたエラーのSynchronous event broadcastingカテゴリーに入ります。

ngAfterViewInitライフサイクルフックは、親コンポーネントの変更が処理された後にトリガされます。子コンポーネントに関連するフックの順序は、Everything you need to know about change detection in Angularで説明されています。 Now Angularは、Appコンポーネントの変更検出を実行したときにfooの値がundefinedであったが、検証フェーズ中に値fooが子のBppコンポーネントによって更新されたことを記憶しています。したがって、エラーが発生します。

What can be done to avoid this error here?

修正と問題は、記事Iリンクに記載されています。ロジックを再設計したくない場合の唯一の安全なオプションは、非同期更新です。また、親コンポーネントの変更検出を実行することもできますが、コンポーネントの変更検出によってコンポーネントの子の変更検出がトリガーされるため、無限ループにつながる可能性があります。病気が影響し

Does ExpressionChangedAfterItHasBeenCheckedError error have ill effects or can it be ignored?

では、アプリケーションApp.foo==='foo'、次のdigest cycle反復までのビュー{{foo}}===undefinedでincosistent状態を持っているということです。開発モードでエラーをオフにすることはできませんが、運用モードでは表示されません。

Two Phases of Angular Applicationsも、このエラーのメンタルモデルを説明するのにはかなり良いです。

+1

私はこれを100万回upvoteすることができます。 – paqogomez

関連する問題