In short:
When testing a component which depends on the callback of setState(updater, callback), it's not working since our last react-native/react upgrade.
In detail:
Since the last react-native upgrade (which comes with react 16 alpha), a test is failing which previously worked. I report this issue here because the production code works. setState(updater, callback) has been changed in react 16, so I assume some enzyme "glue code" does not work anymore.
I've created a snippet which shows the problem:
import React, { Component } from 'react';
import { shallow } from 'enzyme';
import { TextInput } from 'react-native';
class MyTextInput extends Component {
constructor(props) {
super(props);
this.state = {
text: props.text,
// another prop for another TextInput...
};
}
render() {
return (
<TextInput
onChangeText={(text) => {
this.setState({ text }, () => this.props.onChangeText(this.state));
}}
value={this.state.text}
/>
// another TextInput...
);
}
}
describe('MyTextInput', () => {
it('shows the bug', () => {
const onChangeMock = jest.fn();
const textField = shallow(<MyTextInput text={'41'} onChangeText={onChangeMock} />);
textField.simulate('ChangeText', '42');
expect(textField.state('text')).toBe('42'); // OK - setState's updater works
expect(onChangeMock).toHaveBeenCalledTimes(1); // NOT OK - setState's callback is not working
expect(onChangeMock).toHaveBeenCalledWith({ text: '42' }); // NOT OK
});
});
Relevant dependencies:
Thank you in advance!
Enzyme is not currently compatible with react 16 alpha, which also means it's not compatible with a version of RN that requires it.
@rroehrig Update your react-test-renderer as well to @16.0.0-alpha.6 and see if the issue still exists.
@AlbertBrand Thanks for the hint! I tried to update this dependency as well but it's still not working.
Ah, makes sense as you are using Enzyme. I had the same issue but I'm only using the test renderer via Jest. Enzyme probably has its own implementation.
I'm hitting this issue as well but I'm not using enzyme, just [email protected]. @AlbertBrand did you manage to resolve this? Thanks for your help!
I think I have found the issue. react-test-renderer-shallow.development.js has the following:
Updater.prototype.enqueueSetState = function enqueueSetState(publicInstance, partialState, callback, callerName) {
if (typeof partialState === 'function') {
partialState = partialState(publicInstance.state, publicInstance.props);
}
this._renderer._newState = _extends({}, publicInstance.state, partialState);
this._renderer.render(this._renderer._element, this._renderer._context);
};
As you can see, the callback argument is simply ignored, so it is never called. I'm going to try using the full renderer rather than the shallow one and see if it works that way, as react-test-renderer.development.js has the following:
enqueueSetState: function (instance, partialState, callback) {
var fiber = ReactInstanceMap_1.get(instance);
var priorityLevel = getPriorityContext(fiber, false);
callback = callback === undefined ? null : callback;
{
warnOnInvalidCallback(callback, 'setState');
}
addUpdate$1(fiber, partialState, callback, priorityLevel);
scheduleUpdate(fiber, priorityLevel);
}
where the callback argument _is_ used.
UPDATE: It works! Use the following instead of the shallow renderer, and the setState callback is called:
import renderer from 'react-test-renderer'
const deepInstance = renderer.create(<YourComponent />).getInstance()
No solution with enzyme? Using react-test-renderer would completely change the test setup.
with:
"jest": "^23.2.0",
"babel-jest": "^23.2.0",
"enzyme": "^3.3.0",
"react-test-renderer": "^16.4.1",
it doesn't work, setState callback is somehow ignored
@StefanoSega thanks, would you mind filing a new issue about that?
@StefanoSega did you manage to make it work? I got a similar problem
@Soheevich i don鈥檛 think they ever filed an issue; could you file one?
@ljharb Well, I guess this problem doesn't cause by enzyme, because I didn't use it in my project.
Most helpful comment
No solution with enzyme? Using
react-test-rendererwould completely change the test setup.