enzyme: getDerivedStateFromProps not working with setProps

Describe the bug getDerivedStateFromProps don’t called when use setProps on shalow component

To Reproduce Steps to reproduce the behavior:

  1. Use shallow render for component
  2. In getDerivedStateFromProps change state when props change
  3. Use setProps on shallowed component
  4. State not change

Expected behavior setProps should call getDerivedStateFromProps

Packages

  • enzyme@3.6.0
  • enzyme-adapter-react-16@1.5.0
  • react@16.5.1
  • react-dom@16.5.1
  • react-test-render@1.1.1

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

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 2
  • Comments: 15 (8 by maintainers)

Most upvoted comments

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! 🎉

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).

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