Enzyme: UseEffect doesn't run after state updated

Created on 10 Apr 2019  路  14Comments  路  Source: enzymejs/enzyme

Current behavior

Value is the old value of 'Start'

Expected behavior

Value is the new value of 'clicked'

Your environment

Windows

API

  • [ ] mount

Version

| library | version
| ------------------- | -------
| enzyme | 3.9.0
| react | 16.8.6
| react-dom | 16.8.6
| react-test-renderer | 16.8.6
| adapter (below) | 1.12.1

Adapter

  • [ ] enzyme-adapter-react-16
import React, { useEffect, useState } from 'react';
import { mount } from 'enzyme';

export const MyComponent = () => {
    const [value, setValue] = useState('start');
    const [mirror, setMirror] = useState('');
    useEffect(() => {
        console.log(`useEffect sees value of ${value}`);
        setMirror(value);
    }, [value]);
    return (
        <div>
            <button onClick={() => setValue('clicked')} />
            <span>{value}</span>
            <p>{mirror}</p>
        </div>
    );
};

it('renders updated values', () => {
    const wrapper1 = mount(<MyComponent />);
    console.log('Simulating Click');
    wrapper1.find('button').simulate('click');
    console.log('Simulated Click');
    expect(wrapper1.find('span').text()).toContain('clicked');
    expect(wrapper1.find('p').text()).toContain('clicked');
});
question

Most helpful comment

As a workaround you could call

wrapper1.find('button').simulate('click');
wrapper.setProps(); // rerenders
wrapper.update(); // (maybe) additionally necessary

This has the effect that internally a rerender happens and your effect runs.

All 14 comments

I'd suggest avoiding simulate; it doesn't actually simulate anything. Instead, directly invoke the prop function.

Separately, the current version of enzyme doesn't have hooks support - the next one should.

@ljharb, are there any information about the next version?

As a workaround you could call

wrapper1.find('button').simulate('click');
wrapper.setProps(); // rerenders
wrapper.update(); // (maybe) additionally necessary

This has the effect that internally a rerender happens and your effect runs.

wrapper.update() or wrapper.instance().forceUpdate() should cause a rerender, i believe

I find update doesn't rerender a functional component - but setProps does.

I believe that #2135 might have taken care of this.

I'll close for now; we can reopen if the next release (v3.10) doesn't resolve it.

v3.10.0 has now been released.

We are on v3.10.0 and wrapper.update() still doesn't trigger useEffect as opposed to .setProps()

@nkalinov useEffect won't work in shallow until Facebook's shallow renderer supports it.

@ljharb I am talking about mount

In that case, would you mind filing a new issue?

I did not see a new issue for wrapper.update() does not trigger useEffect with mount, so I created one: https://github.com/airbnb/enzyme/issues/2254

Was this page helpful?
0 / 5 - 0 ratings

Related issues

heikkimu picture heikkimu  路  3Comments

nelsonchen90 picture nelsonchen90  路  3Comments

abe903 picture abe903  路  3Comments

AdamYahid picture AdamYahid  路  3Comments

blainekasten picture blainekasten  路  3Comments