Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The state is not reflect in the view when using useEffect and setTimeout #2519

Open
2 of 13 tasks
mrdulin opened this issue May 8, 2021 · 3 comments
Open
2 of 13 tasks

Comments

@mrdulin
Copy link

mrdulin commented May 8, 2021

Current behavior

SomeComponent.tsx:

import React, { ReactElement, useEffect, useState } from 'react';
import { StyledNotifyButton } from './styles';

export const SomeComponent = (): ReactElement => {
  const [showNotifyButton, toggleNotifyButton] = useState(false);

  useEffect(() => {
    setTimeout(() => {
      toggleNotifyButton(true);
    }, 5000);
  }, [toggleNotifyButton]);

  console.log('showNotifyButton: ', showNotifyButton);

  return (
    <div>
      <StyledNotifyButton visible={showNotifyButton} />
    </div>
  );
};

SomeComponent.test.tsx:

import { mount, ReactWrapper } from 'enzyme';
import React from 'react';
import { act } from 'react-dom/test-utils';
import { SomeComponent } from './SomeComponent';

describe('67440874', () => {
  let wrapper: ReactWrapper;

  beforeAll(() => {
    jest.useFakeTimers();
    wrapper = mount(<SomeComponent />);
  });
  it('should pass', () => {
    let notifyButton = wrapper.find('StyledNotifyButton');
    expect(notifyButton.prop('visible')).toBe(false);
    act(() => {
      jest.runOnlyPendingTimers();
    });
    // wrapper.update();
    expect(wrapper.find('StyledNotifyButton').prop('visible')).toBeTruthy();
  });
});

If I don't call wrapper.update() method, the changed state will not reflect in the view.

test result

 FAIL  examples/67440874/SomeComponent.test.tsx
  67440874
    ✕ should pass (11 ms)

  ● 67440874 › should pass

    expect(received).toBeTruthy()

    Received: false

      18 |     });
      19 |     // wrapper.update();
    > 20 |     expect(wrapper.find('StyledNotifyButton').prop('visible')).toBeTruthy();
         |                                                                ^
      21 |   });
      22 | });
      23 | 

      at Object.<anonymous> (examples/67440874/SomeComponent.test.tsx:20:64)

  console.log
    showNotifyButton:  false

      at SomeComponent (examples/67440874/SomeComponent.tsx:13:11)

  console.log
    showNotifyButton:  true

      at SomeComponent (examples/67440874/SomeComponent.tsx:13:11)

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 total
Snapshots:   0 total
Time:        1.542 s, estimated 2 s

Expected behavior

I don't know why I should call wrapper.update() here. As you can see, the state is changed, but the value of the visible prop is not changed.

API

  • shallow
  • mount
  • render

Version

library version
enzyme ^3.11.0
react ^16.14.0
react-dom ^16.14.0
react-test-renderer
adapter (below)

Adapter

  • enzyme-adapter-react-16
  • enzyme-adapter-react-16.3
  • enzyme-adapter-react-16.2
  • enzyme-adapter-react-16.1
  • enzyme-adapter-react-15
  • enzyme-adapter-react-15.4
  • enzyme-adapter-react-14
  • enzyme-adapter-react-13
  • enzyme-adapter-react-helper
  • others ( )
@robertknight
Copy link
Contributor

robertknight commented Sep 16, 2021

I don't know why I should call wrapper.update() here.

Enzyme effectively takes a snapshot of your UI after the initial mount and when you call various Enzyme methods (eg. wrapper.setProps(...)). If you do something which causes the UI outside of Enzyme, such as the act block here, you need to tell Enzyme that the output as changed and it should take a new snapshot that you can then query. This is what wrapper.update() does.

From experience working with developers on my team this aspect of Enzyme can be pretty confusing if you've not developed a good mental model of how it works. It would definitely improve the user experience if the need for this could be eliminated.

@ljharb
Copy link
Member

ljharb commented Sep 16, 2021

@robertknight fwiw v2 did this automatically; unfortunately (as i've come to believe in time) v3 changed this behavior to require an explicit update.

@namgold
Copy link

namgold commented Oct 26, 2021

I have same issue here but in my case, I dont use any setTimeout magic to make Enzyme snapshot out of date.
#2542
Seem that Enzyme's .setProps() does not make Enzyme sync the snapshot as expected. It still requires an additional .update() to be call.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants