Suppose a parent renders <ChildComponent callback={(value)=>setState(value)} />
. Suppose the parent re-renders. The pointer values of the callback
prop will be different (ie. not triple-equals-equal) but the callback
prop's value is conceptually the same for all intents and purposes. This is a "new value" despite being the "same value". You run into the same problem when the parent creates an object <ChildComponent data={{foo: 'bar', bar: 'noise'}} />
(pointers differ, despite it being the "same" object from a value-type perspective).
You also run into the reverse problem due to mutability. Suppose I say:
var value = {foo: 'bar', bar: 'noise'};
ReactDOM.render(<ChildComponent data={value} />, ...);
value.bar = 'drinks';
ReactDOM.render(<ChildComponent data={value} />, ...);
As you can see, the props have clearly "changed" (ie. componentWillReceiveProps
should get called, so the ChildComponent can respond accordingly), but the values are triple-equals-equal.
In general, there is no way to solve this, except to always call componentWillReceiveProps
any time the values might have changed.
If javascript always used value types (like they do for integers; two renders of integers or strings are always "equal" if they are equal from a value-type definition) for all data types, than this problem would not exist. Also, mutation creates an issue, because the meaning of a value can change (when it is mutated) but is still triple-equals equal to the original prop. But because javascript uses reference equality and supports mutation, you can't rely on triple-equals to tell you if two things are conceptually the same.
@kmalakoff Efficiency is an issue, but correctness is also an issue. It's physically not possible, due to javascript's language constraints, to do the equality checks that would be necessary to only call
propsChanged
if the props actually changed (as per above) - that's all I was saying in my comment in facebook/react#3279.(A) is the objective, but it's not clear (yet) what the right solution is. That's the whole topic of facebook/react#3279. The first step to fixing a problem is understanding the problem/usecases.
(B) I don't see any win to separating them, if
propsChanged
still doesn't allow you to assume that the props changed. What is the point in separating them, if you need to do the did-change check anyway?(C) That's already what
shouldComponentUpdate
is intended for; presumably it already (mostly) does that.