Skip to content

OnPush component in dev mode will only trigger change detection once. #39545

@JiaLiPassion

Description

@JiaLiPassion

Consider the following case.

      @Component({
        template: `
          <button (click)="noop()">Trigger change detection</button>
          <div>{{increment('componentView')}}</div>
        `,
        changeDetection: ChangeDetectionStrategy.OnPush
      })
      class App {
        increment() {
          counters++;
        }
        noop() {}
      }
      const fixture = TestBed.createComponent(App);
      fixture.detectChanges();
      expect(counters).toEqual(2); // current behavior is 1 

The reason is App is a OnPush component with a hostView, calling fixture.detectChanges() will run a detectChanges() and checkNoChanges() .
And the App component is onPush, so the checkNoChanges() run will ignore App component, so the counters will be 1
Which is not correct.

Another case is:

    it('works', () => {
      @Component({
        template: '{{message}}',
        changeDetection: ChangeDetectionStrategy.OnPush
      })
      class OnPushCmp {
        @Input() message = 'initial';
        ngAfterViewInit() {
          this.message = 'updated';
        }
      }
      const comp = TestBed.configureTestingModule({declarations: [OnPushCmp]}).createComponent(OnPushCmp);
      expect(() => comp.detectChanges()).toThrow(); // current behavior is not throw.
    });

The reason is the same, the checkNoChanges() will skip the OnPushCmp, so the ExpressionChanged error is not thrown.

Metadata

Metadata

Assignees

Labels

P3An issue that is relevant to core functions, but does not impede progress. Important, but not urgentarea: coreIssues related to the framework runtimecore: change detection

Type

No type
No fields configured for issues without a type.

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions