简体   繁体   中英

React Hooks Wrapper not getting updated after state change in useEffect

Current behaviour

I'm using a functional component with a setState hook in useEffect . The state variable that is set inside useEffect is wrapped over the return statement to render the JSX for the component.

When I debug into it, the component renders with the correct state variable but my wrapper in my test does Not show the correct information.

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

Below is a snippet of what I am trying to achieve:

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

    useEffect(() => {
      setSelected(true)
    }, [someDependency])

    return (
      { 
         selected && (
         <div id= 'container'>
            {childComponents}
          </div>)
       }
    );
    })

it('test', () => {
     const wrapper= mount( <DummyComponent  /> ); 
    wrapper = wrapper.update(); // this doesn't fix my problem   
    wrapper.find('#container')first().props().onClick();
    expect(wrapper.toMatchSnapshot());
});

I am getting the below error:

Method “props” is meant to be run on 1 node. 0 found instead.

Expected Behaviour

After state update in useEffect re-render should be triggered in test case and element with id="container" should be found.

Note: This is not same as https://github.com/enzymejs/enzyme/issues/2305

It seems to me there's some other problem with your real code (maybe some promise-based code invoked in the effect?). Here's a working example based on your snippet:

const DummyComponent = ({}) => {
    const [selected, setSelected] = React.useState(false);
    const [result, setResult] = React.useState("");

    React.useEffect(() => {
        setSelected(true);
    }, []);

    return selected && <div id='container' onClick={() => setResult("test")}>
        <label>{result}</label>
    </div>;
};

it('test', () => {
    const wrapper = mount(<DummyComponent/>);
    act(() => {
        wrapper.find('#container').first().props().onClick();
    });
    expect(wrapper.find("label").text()).toEqual("test");
});

The act is actually needed only for interaction with the component itself, not for after-render effect.

The problem is that when you first mount the component, it does not render anything, because selected is false. So, when you search for '#container' , you don't get anything.

If the update is enough, then it should probably be executed before the wrapper.find() , so that the component is rendered with selected true. But React is asynchronous and I suspect that this will not be enough…

I fixed my problem, actually I need to assign my component to a different wrapper and then update the wrapper and then check for updates on the wrapper instead of the component. Below is the snippet:

it('test', () => {

     const component= mount( <DummyComponent  /> ); 
     const wrapper = component.update();  
     wrapper.find('#container')first().props().onClick();
     expect(wrapper.toMatchSnapshot());

}); 

This will have the updated component

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM