-
Notifications
You must be signed in to change notification settings - Fork 50k
Description
I know this.context is not officially there but quite a few libraries rely on it, and it seems like it's getting into shape with #2509.
I'm trying to understand how exactly shouldComponentUpdate is supposed to be implemented with context in mind. I noticed it accepts a third argument (nextContext) and I can extend PureRenderMixin to also check it:
shouldComponentUpdate: function(nextProps, nextState, nextContext) {
return !shallowEqual(this.props, nextProps) ||
!shallowEqual(this.state, nextState) ||
!shallowEqual(this.context, nextContext); // this will throw without context, read on
}Components that don't opt into this.context by not omitting contextTypes will not get this third argument, which is understandable.
However this presents a problem when we have a <Middle /> component in between between <Top /> context owner and <Bottom /> context consumer. If <Middle /> implements a restrictive shouldComponentUpdate, there is no way for <Bottom /> to react to <Top />'s context updates at all:
(fiddle)
var Bottom = React.createClass({
contextTypes: {
number: React.PropTypes.number.isRequired
},
render: function () {
return <h1>{this.context.number}</h1>
}
});
var Middle = React.createClass({
shouldComponentUpdate: function (nextProps, nextState, nextContext) {
return false;
},
render: function () {
return <Bottom />;
}
});
var Top = React.createClass({
childContextTypes: {
number: React.PropTypes.number.isRequired
},
getInitialState: function () {
return { number: 0 };
},
getChildContext: function () {
return { number: this.state.number };
},
componentDidMount: function () {
setInterval(function () {
this.setState({
number: this.state.number + 1
});
}.bind(this), 1000);
},
render: function() {
return <Middle />;
}
});
React.render(<Top />, document.body);The same problem would occur if I tried to give Middle a generic context-aware shouldComponentUpdate as I wrote above, because Middle has no this.context unless it opts in.
This is possible to work around by adding contextTypes to Middle, but it doesn't look like a good solution. You'd need to explicitly add necessary contextTypes on every level with smart shouldComponentUpdate so it's too easy to slip up.
Will this be solved by #2112? Is there another solution in the meantime? What is the recommended way?