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

Functional component and useState hooks - wrapper not reflecting changes after rerender triggered by setState #2305

Closed
2 of 13 tasks
makr28 opened this issue Dec 9, 2019 · 13 comments

Comments

@makr28
Copy link

makr28 commented Dec 9, 2019

Current behavior

I'm using a functional component with a setState hook. I am calling a function in the component that uses that setState hook's setter function. The state variable that is set is used in the return of the functional component to pass something to a child component.

When I debug into it, the component renders with the correct state variable and the child component having the correct props But my wrapper in my test does Not show the correct information is being passed to the child component.

wrapper.update() isn't fixing this issue.

Here's a quick basic watered down example of what i am doing (component and test)

 const wrapper= ({}) => {
    const [selected, setSelected] = React.useState(0);

    function handleOnSomething(idx) {
      setSelected(idx)
   }

    return (
      <div>
        <item onSomething={handleOnSomething} isSelected={selected === 0}/>
        <item onSomething={handleOnSomething} isSelected={selected === 1}/>
      </div>
  );
})

it('test', () => {
    const wrapper= shallow(<wrapper  />);    
    wrapper.find('selector2ndItem').prop('onSomething')(1); // this method calls the setter

    wrapper.update(); // this doesnt fix my problem

    const item2 = viewer.find(selector2ndItem);

    // should be correct and is when debugging but wrapper doesn't have the changes 
    expect(item2.props().isSelected).toEqual(true); // isSelected still === false
});

Basically the test should set the 2nd item's isSelected to true. It does in the code when I debug, but the wrapper in the test doesn't show those changes.

Expected behavior

I expect item2 isSelected to equal true. When I debug into the code I see the rerender after 'setSelected' is called and it renders with the correctly selected item. In the test I cant see that though. When I do wrapper.debug() it show the old information

Your environment

Windows 10
visual studio code

API

  • shallow
  • mount
  • render

Version

library version
enzyme ^3.3.0
react ^16.2.0
react-dom ^16.2.0
react-test-renderer ^16.2.0
adapter (below)

All enzyme stuff in my package.json
"enzyme": "^3.3.0",
"enzyme-adapter-react-16": "^1.1.1",
"enzyme-react-intl": "^1.4.8",
"enzyme-redux": "^0.2.1",
"enzyme-to-json": "^3.3.3",

React Intl:
"react-intl": "^2.3.0",

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 ( )
@prawana-perera
Copy link

I'm having the same issue

@josh08h
Copy link

josh08h commented Mar 16, 2020

Is there any movement on this?

I'm seeing the same issue with enzyme@3.11.0 and react@16.8.1.

As things stand I can't use React hooks with enzyme.

Note mount seems to work.

@skyboyer
Copy link
Contributor

for unknown reason invoke() or simulate() may work well when props(...)() call does not update wrapper. Honestly did not catch any specific conditions, but it happens not to all my components.

@josh08h
Copy link

josh08h commented Mar 16, 2020

Upgrading to react@16.13.0 fixed the issue.

@kennethnym
Copy link

@josh08h Same issue on react 16.13.1

@bdwain
Copy link
Contributor

bdwain commented May 13, 2020

@makr28 what is viewer? And have you tried changing wrapper to Wrapper? Idk if it matters anymore, but in the past I've seen react treat lowercased things as dom elements and not components

@bdwain
Copy link
Contributor

bdwain commented May 13, 2020

This seems to work for me in a code sandbox https://codesandbox.io/s/eloquent-violet-x8gjh?file=/src/index.js

@revoyrm
Copy link

revoyrm commented May 15, 2020

@bdwain "viewer" was a mistake on my part, i copied a test of ours and changed viewer to wrapper to be more generic in my question. I just forgot to change that instance to "wrapper". I haven't gotten a chance to try this. I found a different way to somewhat test what I needed for my project.

If everyone else says 16.13.1 fixed this, I'm cool with this getting closed.

@mikeyrt16
Copy link

@revoyrm

If everyone else says 16.13.1 fixed this, I'm cool with this getting closed.

I'm not sure anyone has said this. I'm running 16.13.1 and have this issue.

Do anyone have any update on this? 🙏

@ljharb
Copy link
Member

ljharb commented Aug 29, 2020

a PR with failing test cases would be appreciated; it's much easier for me to come up with a fix from that.

@rulyotano
Copy link

I got to this issue and after trying some variants, I think this one solved the problem. The key I think is in updating the wrapper after the update: wrapper = wrapper.update(), and then find the element again. The test code:

  test('canGoNext should be false initially and true when key has length = 8', () => {
    let wrapper = mountWrapper();
    let wizard = wrapper.find(Wizard);

    expect(wizard.props().canGoNext).toBeFalsy();

    const signKey = wrapper.find(SignatureKeyInput);
    act(() => {
      signKey.props().onChange('12345678');
    });
    wrapper = wrapper.update();
    wizard = wrapper.find(Wizard);
    expect(wizard.props().canGoNext).toBeTruthy();
  });

@nehawork

This comment has been minimized.

@ljharb ljharb closed this as completed Feb 19, 2021
@i3web

This comment has been minimized.

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

No branches or pull requests