mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Call refs and lifecycles on indeterminate components (#8614)
This was a bug because of the split between ClassComponent and IndeterminateComponent -- we didn't mark effects or push context when we come from an indeterminate component. Now they behave the same way. The code is even clumsier than before but I'm pretty worried we'll screw these up in the future if we don't unify the paths. Not many components exercise this path but Relay containers do so it's noticeable.
This commit is contained in:
@@ -1343,6 +1343,7 @@ src/renderers/shared/shared/__tests__/ReactComponentLifeCycle-test.js
|
||||
* should not throw when updating an auxiliary component
|
||||
* should allow state updates in componentDidMount
|
||||
* should call nested lifecycle methods in the right order
|
||||
* calls effects on module-pattern component
|
||||
|
||||
src/renderers/shared/shared/__tests__/ReactCompositeComponent-test.js
|
||||
* should support module pattern components
|
||||
|
||||
@@ -229,7 +229,10 @@ module.exports = function<T, P, I, TI, C, CX>(
|
||||
} else {
|
||||
shouldUpdate = updateClassInstance(current, workInProgress, priorityLevel);
|
||||
}
|
||||
return finishClassComponent(current, workInProgress, shouldUpdate);
|
||||
}
|
||||
|
||||
function finishClassComponent(current : ?Fiber, workInProgress : Fiber, shouldUpdate : boolean) {
|
||||
// Schedule side-effects
|
||||
if (shouldUpdate) {
|
||||
workInProgress.effectTag |= Update;
|
||||
@@ -411,14 +414,13 @@ module.exports = function<T, P, I, TI, C, CX>(
|
||||
workInProgress.tag = ClassComponent;
|
||||
adoptClassInstance(workInProgress, value);
|
||||
mountClassInstance(workInProgress, priorityLevel);
|
||||
ReactCurrentOwner.current = workInProgress;
|
||||
value = value.render();
|
||||
return finishClassComponent(current, workInProgress, true);
|
||||
} else {
|
||||
// Proceed under the assumption that this is a functional component
|
||||
workInProgress.tag = FunctionalComponent;
|
||||
reconcileChildren(current, workInProgress, value);
|
||||
return workInProgress.child;
|
||||
}
|
||||
reconcileChildren(current, workInProgress, value);
|
||||
return workInProgress.child;
|
||||
}
|
||||
|
||||
function updateCoroutineComponent(current, workInProgress) {
|
||||
|
||||
@@ -594,4 +594,55 @@ describe('ReactComponentLifeCycle', () => {
|
||||
'inner componentWillUnmount',
|
||||
]);
|
||||
});
|
||||
|
||||
it('calls effects on module-pattern component', function() {
|
||||
const log = [];
|
||||
|
||||
function Parent() {
|
||||
return {
|
||||
render() {
|
||||
expect(typeof this.props).toBe('object');
|
||||
log.push('render');
|
||||
return <Child />;
|
||||
},
|
||||
componentWillMount() {
|
||||
log.push('will mount');
|
||||
},
|
||||
componentDidMount() {
|
||||
log.push('did mount');
|
||||
},
|
||||
componentDidUpdate() {
|
||||
log.push('did update');
|
||||
},
|
||||
getChildContext() {
|
||||
return {x: 2};
|
||||
},
|
||||
};
|
||||
}
|
||||
Parent.childContextTypes = {
|
||||
x: React.PropTypes.number,
|
||||
};
|
||||
function Child(props, context) {
|
||||
expect(context.x).toBe(2);
|
||||
return <div />;
|
||||
}
|
||||
Child.contextTypes = {
|
||||
x: React.PropTypes.number,
|
||||
};
|
||||
|
||||
const div = document.createElement('div');
|
||||
ReactDOM.render(<Parent ref={(c) => c && log.push('ref')} />, div);
|
||||
ReactDOM.render(<Parent ref={(c) => c && log.push('ref')} />, div);
|
||||
|
||||
expect(log).toEqual([
|
||||
'will mount',
|
||||
'render',
|
||||
'did mount',
|
||||
'ref',
|
||||
|
||||
'render',
|
||||
'did update',
|
||||
'ref',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user