enzymejs / enzymejs/enzyme

componentDidUpdate() does not get called when .setProps() is called with new props

Open
#2,197 10 comments 2 reactions 0 assignees View on GitHub
Need To Reproduce
Dominant language
JavaScript
Stars
19.8k
Forks
2k
PR merge metrics
No merged PRs in 30d

Description

The [shallow docs](https://airbnb.io/enzyme/docs/api/shallow.html#shallow-rendering-api) explicitly indicate that the `componentDidUpdate` lifecycle method will get called by shallow mounted components, yet given the following test case this is not actually happening:
```
import { shallow } from 'enzyme';
import React from 'react';
import PropTypes from "prop-types";
import { isEqual } from 'lodash';

class Foo extends React.Component {
static propTypes = {
values: PropTypes.arrayOf(PropTypes.number).isRequired
};

static computeTotal(values) {
return values.reduce((total, value) => {
return total + value;
}, 0);
}

constructor(props) {
super(props);
this.state = {
totalValue: Foo.computeTotal(props.values)
};
}

componentDidUpdate(prevProps) {
const { values } = this.props;
const { values: oldValues } = prevProps;
if (!isEqual(values, oldValues)) {
this.setState({ totalValue: Foo.computeTotal(values) });
}
}

render() {
const { values } = this.props;
const { totalValue } = this.state;

return (

{values.join(' + ')} = {totalValue}
);
}
}

describe('Foo', () => {
let wrapper;
beforeAll(() => {
wrapper = shallow();
});
it('has the expected total', () => {
expect(wrapper.text()).toEqual('1 + 2 = 3');
});
it('changing values updates total', () => {
wrapper.setProps({ values: [2, 3] });
expect(wrapper.text()).toEqual('2 + 3 = 5');
});
});
```

### Current behavior
Foo
✓ has the expected total (7ms)
✕ changing values updates total (8ms)

● Foo › changing values updates total

expect(received).toEqual(expected) // deep equality

Expected: "2 + 3 = 5"
Received: "2 + 3 = 3"

48 | it('changing values updates total', () => {
49 | wrapper.setProps({ values: [2, 3] });
> 50 | expect(wrapper.text()).toEqual('2 + 3 = 5');
| ^
51 | });
52 | });
53 |

### Expected behavior
Both tests pass

### Your environment
node: 12.4.0

#### API

- [x] shallow
- [ ] mount
- [ ] render

#### Version

| library | version
| ------------------- | -------
| enzyme | 3.10.0
| react | 16.8.6
| react-dom | 16.8.6
| react-test-renderer | 16.8.6
| adapter (below) | 1.14.0

#### Adapter

- [x] enzyme-adapter-react-16
- [ ] enzyme-adapter-react-16.3
- [ ] enzyme-adapter-react-16.2
- [ ] enzyme-adapter-react-16.1
- [ ] enzyme-adapter-react-15
- [ ] enzyme-adapter-react-15.4
- [ ] enzyme-adapter-react-14
- [ ] enzyme-adapter-react-13
- [ ] enzyme-adapter-react-helper
- [ ] others ( )

Contributor guide

Open the contributing guide

Research direction

Start with the shallow API documentation and reproduce the supplied Foo example using setProps() and componentDidUpdate(). Trace the shallow update path to determine why the lifecycle method does not update state, then verify that both shown expectations pass without changing mount or render behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, react
Domain
frontend, testing
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.