Running wrapper.setProps({ foo: 'bar' }) does not trigger getDerivedStateFromProps when the component is shallowly rendered.
Running wrapper.setProps({ foo: 'bar' }) should trigger getDerivedStateFromProps when the component is shallowly rendered.
React 16.3, macOS High Sierra
| library | version
| ---------------- | -------
| Enzyme | 3.3.0
| React | 16.3.0
@mneumark
What's the version of react-test-renderer?
That works fine in my environment.
const Enzyme = require('enzyme');
const React = require('react');
const Adapter = require('enzyme-adapter-react-16');
const assert = require('assert');
Enzyme.configure({adapter: new Adapter()});
const {shallow} = Enzyme;
class App extends React.Component {
static getDerivedStateFromProps(nextProps) {
console.log('getDerivedStateFromProps', nextProps);
return null;
}
render() {
return <section>
{this.props.name}
</section>
;
}
}
const wrapper = Enzyme.shallow(<App name="foo" />);
wrapper.setProps({name: 'bar'});
// getDerivedStateFromProps { name: 'foo' }
// getDerivedStateFromProps { name: 'bar' }
Working correctly here with "react-test-renderer": "16.3.0".
Hmm, I'm using 16.3.0. Just so I don't feel crazy, upgrading to 16.3 should only entail bumping the versions of react, react-dom and react-test-renderer?
@psychowico and @koba04 when i return null from getDerivedStateFromProps its all good, but if i return an object the entire thing won't mount.
Edit: IF i return the entire prevState object its all good too.
The component I was using had getDerivedStateFromProps returning an object 100% of the time, and I was defining this.state in my constructor. Hope that information is helpful.
@mneumark in my case state included a key that was set to an index value. In the render method we were accessing an array by index and getting a value in the object at that index. if index was, for some reason, not set, it would fail. State was initialized with that key as an index of 0, however for some reason during mount() getDerivedStateFromProps was being called with nextProps.key set as null. This is most likely an issue in our implementation (its entirely feasible for this particular prop to be not provided or null by the parent).
once I fixed that issue it behaves as expected and all tests pass.
Except I had a console.log as the first line of getDerivedStateFromProps and it wasn't being triggered so I have to assume that its not an issue like that as it was not getting into the function in the first place. But everything worked fine once I switched from shallow to mount...
FWIW, I am experiencing the same issue, using @koba04 sample file with [email protected], [email protected], [email protected], getDerivedStateFromProps is not being called when using shallow but it works when using mount
I am also encountering the same issue when using enzyme shallow setProps where getDerivedStateFromProps does not get triggered at all. I have [email protected] [email protected] [email protected] [email protected]. Please help. :)
I had to install enzyme-adapter-react-16@next in addition to [email protected], [email protected], and [email protected] in order to get the getDerivedStateFromProps lifecycle method to run on shallow render. I hope that helps.
It works now with enzyme-adapter-react-16@next. Thanks jhaddow! :)
Can confirm the issue with getDerivedStateFromProps is not called. Just a heads up with enzyme-adapter-react-16@next points to 1.0.0-beta.7. I was able to run the following test up until [email protected] (that's newer than @next):
Other versions:
Test:
import React, { Component } from 'react';
import { shallow } from 'enzyme';
const orderCallback = jest.fn();
class Lifecycle extends Component {
static getDerivedStateFromProps(nextProps, prevState) {
orderCallback('getDerivedStateFromProps');
return { foo: !prevState.foo };
}
constructor(props) {
super(props);
orderCallback('constructor');
}
state = { foo: true };
render() {
orderCallback('render');
return this.state.foo;
}
}
describe('React Lifecycle', () => {
beforeEach(() => {
orderCallback.mockReset();
});
it('renders in correct order', () => {
shallow(<Lifecycle />);
expect(orderCallback.mock.calls[0][0]).toBe('constructor');
expect(orderCallback.mock.calls[1][0]).toBe('getDerivedStateFromProps');
expect(orderCallback.mock.calls[2][0]).toBe('render');
expect(orderCallback.mock.calls.length).toBe(3);
});
});
I don't know what happened but it seems to work now with [email protected]. Sigh.
@GenghisKhan very strange - now my test with @1.1.1 pass 馃
Maybe it's a silent update. Lol
@hkjorgensen @GenghisKhan it could be that a newer version of react-test-renderer is installed when you re-install enzyme-adapter-react-16

I have 16.3.2 installed as a package.json dep, but I installed enzyme-adapter-react-16 awhile ago and that is still on 16.2.0
TO SOLVE THIS ISSUE
$ yarn remove enzyme-adapter-react-16
$ yarn add enzyme-adapter-react-16
reason: The sub-dependency of react-test-renderer for enzyme-react-adapter-16 is not updated by npm/yarn, removing the package and re-adding it will get the latest version of that dependency.
Ran some additional tests, using [email protected], [email protected], [email protected]
Using [email protected] and [email protected], tests still fail, getDerivedStateFromProps is not called when using Enzime.shallow()
yarn add --dev enzyme-adapter-react-16@next, install [email protected] and [email protected]
Now the test works, getDerivedStateFromProps is being called
yarn add --dev [email protected] upgrades this package, but enzyme-adapter-utils is not updated, still in [email protected]
My guess at this point, keeping [email protected] works
Really weird issue, created a new repository just to test this, I was trying to reproduce my previous results in a clean environment.
https://github.com/jhcaiced/react-enzyme-issue-1600
It works perfectly, using [email protected], [email protected], [email protected], [email protected] and [email protected]
@jhcaiced read https://github.com/airbnb/enzyme/issues/1600#issuecomment-384113704
Thanks @audiolion, your workaround works, but the package name is wrong in the comment, here is what I run for my project
yarn remove enzyme-adapter-react-16
yarn add --dev enzyme-adapter-react-16
As an alternative to remove/add, one can also add a selective version resolution to package.json:
"resolutions": {
"enzyme-adapter-react-16/react-test-renderer": "^16.3.2"
}
and then yarn install.
Ensuring the react-test-renderer version used by enzyme-adapter-react-16 is 16.3.2 now has getDerivedStateFromProps() being called as expected when using shallow().
the next tag was from before the v3 release; you don't want to be using that.
It seems like the real issue is that the test renderer needs to match your react version.
I'm not sure how to resolve this short of creating enzyme-adapter-react-16.3, since 16.2 should not be invoking the new lifecycle methods.
@ljharb
I'm not sure how to resolve this short of creating enzyme-adapter-react-16.3, since 16.2 should not be invoking the new lifecycle methods.
From v16.4, React changed the behavior of getDerivedStateFromProps, which is called for any updates even if the update is invoked by setState.
Before v16.4, React called getDerivedStateFromProps only when props are updated.
https://reactjs.org/blog/2018/05/23/react-v-16-4.html#bugfix-for-getderivedstatefromprops
So if we create enzyme-adapter-react-16.3, we also have to create enzyme-adapter-react-16.4 to follow the different behavior.
getDerivedStateFromProps is called in react-test-renderer so enzyme is not doing anything.
Isn't it enough only to move react-test-renderer from depenedencies to peerDependencies?
https://github.com/airbnb/enzyme/blob/master/packages/enzyme-adapter-react-16/package.json#L44
But it might make sense to create enzyme-adapter-react16.2 to support getSnapshotBeforeUpdate and fix react-test-renderer version.
@koba04 we now have 16.1- and 16.2-specific adapters; if there's further changes needed, PRs are very appreciated.
I believe this is addressed; I'm going to close it. Please file a new issue if there's still issues.
Most helpful comment
@hkjorgensen @GenghisKhan it could be that a newer version of
react-test-rendereris installed when you re-installenzyme-adapter-react-16I have
16.3.2installed as apackage.jsondep, but I installedenzyme-adapter-react-16awhile ago and that is still on16.2.0TO SOLVE THIS ISSUE
reason: The sub-dependency of
react-test-rendererforenzyme-react-adapter-16is not updated bynpm/yarn, removing the package and re-adding it will get the latest version of that dependency.