Describe the bug
getDerivedStateFromProps don't called when use setProps on shalow component
To Reproduce
Steps to reproduce the behavior:
getDerivedStateFromProps change state when props changesetProps on shallowed componentExpected behavior
setProps should call getDerivedStateFromProps
Packages
Example
tabs.jsx
export class Tabs extends PureComponent {
static getDerivedStateFromProps(props, state) {
const { activeTab } = props;
if (activeTab !== state.activeTab) {
return { activeTab };
}
return null;
}
state = {
activeTab: 0,
};
// ...other code
}
tabs.test.jsx
wrapper = shallow((
<Tabs border>
<Tab label="test">tab content 1</Tab>
<Tab label="test">tab content 2</Tab>
</Tabs>
));
test('GDSFP', () => {
const expectedValue = 'test123';
wrapper.setProps({ activeTab: expectedValue });
epxect(wrapper.state().activeTab).toBe(expectedValue);
});
Thanks for the repro steps - can you provide the actual _code_ you used when seeing this?
We have explicit tests for this already: https://github.com/airbnb/enzyme/blob/master/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx#L5004-L5050
are you sure the method isn't being called?
@ljharb Add example to issue. I create new empty component and it's not working
"enzyme": "3.6.0"
"enzyme-adapter-react-16": "1.5.0"
"react": "16.5.1"
import React, { Component } from ‘react’;
import PropTypes from ‘prop-types’;
export class TestMe extends Component {
static propTypes = {
activeTab: PropTypes.string,
};
state = {
activeTab: null,
};
static getDerivedStateFromProps(props, state) {
const { activeTab } = props;
if (activeTab !== state.activeTab) {
return { activeTab };
}
return null;
}
render() {
return <div>{this.state.activeTab}</div>;
}
}
import { TestMe } from ‘./test-me’;
describe(‘<TestMe />’, () => {
test(‘should match snapshot’, () => {
const wrapper = shallow(<TestMe activeTab=“1” />);
expect(wrapper.state()).toMatchObject({
activeTab: ‘1’, // FAILS: activeTab is null
});
wrapper.setProps({
activeTab: ‘2’,
});
expect(wrapper.state()).toMatchObject({
activeTab: ‘2’, // FAILS: activeTab is null
});
});
});
hmm, the test is passing in my environment.
it('pass the test', () => {
class TestMe extends React.Component {
constructor(props) {
super(props);
this.state = {
activeTab: null,
};
}
static getDerivedStateFromProps(props, state) {
const { activeTab } = props;
if (activeTab !== state.activeTab) {
return { activeTab };
}
return null;
}
render() {
return <div>{this.state.activeTab}</div>;
}
}
const wrapper = shallow(<TestMe activeTab="1" />);
expect(wrapper.state()).to.have.property('activeTab', '1');
wrapper.setProps({
activeTab: '2',
});
expect(wrapper.state()).to.have.property('activeTab', '2');
});
Note that enzyme doesn’t have snapshot support; the closest would be debug()
I've experienced the same issue, with getDerivedStateFromProps only being called during the initial shallow render and not during setProps (on latest enzyme and react).
@koba04 What react version you have?
@merrywhether Have you solved this problem?
@merrywhether can you share your versions of react, enzyme, and your react adapter?
@OverVlad [email protected]
@koba04 But for me now working in all my project if I setup latest react with latest enzyme
@OverVlad ok, if you've updated everything and everything is working, then it seems like this is resolved. Happy to reopen it if that's not the case.
Sorry for slow:
"react": "16.5.1",
"enzyme": "3.6.0",
"enzyme-adapter-react-16": "1.5.0",
@merrywhether can you share your component and test code?
Update: the problem was that yarn had pinned my version of react-test-renderer (which was not a direct dependency) to 16.0.0 (via yarn.lock). Forcing that to update seems to have fixed it! 🎉