Skip to content

rerender does recreate the component breaking ngOnChanges #360

Closed
@shaman-apprentice

Description

@shaman-apprentice

Bug

First of all of course thx for all the great open source work done! :)

Expected behavior

GIVEN a component which depends on previous value within ngOnChanges
WHEN calling rerender with new input properties
THEN ngOnChanges gets called with previous and new current value.

Actual behavior

The component gets recreated and changes within ngOnChanges are always initial changes.

Minimal reproduction

The second expect in the test below will fail.

@Component({
  selector: 'atl-fixture-2',
  template: `{{
    hasImproved
      ? 'Great, I cannot remember any result as good as yours! Keep throwing!'
      : 'You can do better than that... Try again!'
  }}`,
})
class MotivatorComponent implements OnChanges {
  @Input() dice = 1;

  hasImproved = false;

  ngOnChanges(changes: SimpleChanges): void {
    console.log(changes.dice);
    if (!changes.dice.firstChange && changes.dice) {
      this.hasImproved = changes.dice.currentValue > changes.dice.previousValue;
    }
  }
}

test('"ngOnChanges" gets called with an update', async () => {
  const { rerender } = await render(MotivatorComponent, {
    componentInputs: { dice: 1 },
  });

  expect(screen.getByText('You can do better than that... Try again!')).toBeInTheDocument();

  await rerender({
    componentInputs: {
      dice: 2,
    },
  });

  expect(screen.getByText('Great, I cannot remember any result as good as yours! Keep throwing!')).toBeInTheDocument();
});

The two console logs will be:

console.log
    SimpleChange {
      previousValue: undefined,
      currentValue: 1,
      firstChange: true
    }

      at MotivatorComponent.ngOnChanges (tests/rerender.spec.ts:75:13)

  console.log
    SimpleChange {
      previousValue: undefined,
      currentValue: 2,
      firstChange: true
    }

The actual console logs in a small demo app are:

{previousValue: undefined, currentValue: 1, firstChange: true}
{previousValue: 1, currentValue: 2, firstChange: false}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions