diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.js b/packages/react-reconciler/src/ReactFiberBeginWork.js index 3c20dceacf3fb..dcd6246f7c7a7 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.js @@ -838,6 +838,8 @@ export default function( } let sibling = nextFiber.sibling; if (sibling !== null) { + // Set the return pointer of the sibling to the work-in-progress fiber. + sibling.return = nextFiber.return; nextFiber = sibling; break; } diff --git a/packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js b/packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js index 0a4763a4fec8a..9a87f02fda9fe 100644 --- a/packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js @@ -989,6 +989,82 @@ describe('ReactNewContext', () => { ReactNoop.flush(); }); + // This is a regression case for https://github.com/facebook/react/issues/12686 + it('does not skip some siblings', () => { + const Context = React.createContext(0); + + class App extends React.Component { + state = { + step: 0, + }; + + render() { + ReactNoop.yield('App'); + return ( + + + {this.state.step > 0 && } + + ); + } + } + + class StaticContent extends React.PureComponent { + render() { + return ( + + + + + + + ); + } + } + + class Indirection extends React.PureComponent { + render() { + return ; + } + } + + function Consumer() { + return ( + + {value => { + ReactNoop.yield('Consumer'); + return ; + }} + + ); + } + + // Initial mount + let inst; + ReactNoop.render( (inst = ref)} />); + expect(ReactNoop.flush()).toEqual(['App']); + expect(ReactNoop.getChildren()).toEqual([ + span('static 1'), + span('static 2'), + ]); + // Update the first time + inst.setState({step: 1}); + expect(ReactNoop.flush()).toEqual(['App', 'Consumer']); + expect(ReactNoop.getChildren()).toEqual([ + span('static 1'), + span('static 2'), + span(1), + ]); + // Update the second time + inst.setState({step: 2}); + expect(ReactNoop.flush()).toEqual(['App', 'Consumer']); + expect(ReactNoop.getChildren()).toEqual([ + span('static 1'), + span('static 2'), + span(2), + ]); + }); + describe('fuzz test', () => { const Fragment = React.Fragment; const contextKeys = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];