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.
I might add one more principle (I was also using it implicitly):
(D) simplify method naming
My thinking is that the names are very verbose and so I end up copying any pasting instead of typing which signals that there could be room for improvement. Since we are moving towards an ES6 world and there are compilers like Babel, let's assume the use of React.Component and simplify the naming.
Here are some proposals to consider:
(1a) Very minimal API - it might be clearer to use the word render instead of update:
(1b) Very minimal API:
(2a) Slightly more expanded API - it might be clearer to use the word render instead of update:
(2a) Slightly more expanded API:
I'm actually not sure if the other methods are necessary so it should be analyzed and based on the findings, the principles could be updated.