enzyme: UseEffect doesn't run after state updated

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');
});

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 16 (9 by maintainers)

Most upvoted comments

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.

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

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

@ljharb I am talking about mount

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