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?