Skip to content

Commit 343fb95

Browse files
authored
Add test for componentDidUpdate with a bailout in the middle (#8525)
This is one of the cases where Fiber diverges.
1 parent 17f8e94 commit 343fb95

File tree

2 files changed

+87
-0
lines changed

2 files changed

+87
-0
lines changed

scripts/fiber/tests-passing.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1294,6 +1294,7 @@ src/renderers/shared/shared/__tests__/ReactCompositeComponentDOMMinimalism-test.
12941294

12951295
src/renderers/shared/shared/__tests__/ReactCompositeComponentState-test.js
12961296
* should support setting state
1297+
* should call componentDidUpdate of children first
12971298
* should batch unmounts
12981299

12991300
src/renderers/shared/shared/__tests__/ReactEmptyComponent-test.js

src/renderers/shared/shared/__tests__/ReactCompositeComponentState-test.js

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
var React;
1515
var ReactDOM;
16+
var ReactDOMFeatureFlags;
1617

1718
var TestComponent;
1819

@@ -22,6 +23,7 @@ describe('ReactCompositeComponent-state', () => {
2223
React = require('React');
2324

2425
ReactDOM = require('ReactDOM');
26+
ReactDOMFeatureFlags = require('ReactDOMFeatureFlags');
2527

2628
TestComponent = React.createClass({
2729
peekAtState: function(from, state) {
@@ -227,6 +229,90 @@ describe('ReactCompositeComponent-state', () => {
227229
expect(stateListener.mock.calls.join('\n')).toEqual(expected.join('\n'));
228230
});
229231

232+
233+
it('should call componentDidUpdate of children first', () => {
234+
var container = document.createElement('div');
235+
236+
var ops = [];
237+
238+
var child = null;
239+
var parent = null;
240+
241+
class Child extends React.Component {
242+
state = {bar:false};
243+
componentDidMount() {
244+
child = this;
245+
}
246+
componentDidUpdate() {
247+
ops.push('child did update');
248+
}
249+
render() {
250+
return <div />;
251+
}
252+
}
253+
254+
var shouldUpdate = true;
255+
256+
class Intermediate extends React.Component {
257+
shouldComponentUpdate() {
258+
return shouldUpdate;
259+
}
260+
render() {
261+
return <Child />;
262+
}
263+
}
264+
265+
class Parent extends React.Component {
266+
state = {foo:false};
267+
componentDidMount() {
268+
parent = this;
269+
}
270+
componentDidUpdate() {
271+
ops.push('parent did update');
272+
}
273+
render() {
274+
return <Intermediate />;
275+
}
276+
}
277+
278+
ReactDOM.render(<Parent />, container);
279+
280+
ReactDOM.unstable_batchedUpdates(() => {
281+
parent.setState({ foo: true });
282+
child.setState({ bar: true });
283+
});
284+
// When we render changes top-down in a batch, children's componentDidUpdate
285+
// happens before the parent.
286+
expect(ops).toEqual([
287+
'child did update',
288+
'parent did update',
289+
]);
290+
291+
shouldUpdate = false;
292+
293+
ops = [];
294+
295+
ReactDOM.unstable_batchedUpdates(() => {
296+
parent.setState({ foo: false });
297+
child.setState({ bar: false });
298+
});
299+
// We expect the same thing to happen if we bail out in the middle.
300+
expect(ops).toEqual(
301+
ReactDOMFeatureFlags.useFiber ?
302+
[
303+
// Fiber works as expected
304+
'child did update',
305+
'parent did update',
306+
] : [
307+
// Stack treats these as two separate updates and therefore the order
308+
// is inverse.
309+
'parent did update',
310+
'child did update',
311+
]
312+
);
313+
314+
});
315+
230316
it('should batch unmounts', () => {
231317
var outer;
232318

0 commit comments

Comments
 (0)