Have you thought about how React compares the deps
array used by the hooks in every render? Let's check the magic that decides when to run the useEffect
hook.
Introduction
As a curious developer, I was wondering how React checks the dependencies array -called deps
- that is passed to the useEffect
, useCallback
and useMemo
hooks. I didn't find the answer anywhere.
useEffect(() => {
console.log('someValue has changed:', someValue);
}, [someValue]);
So, my only option was to check the React's code itself to find the magic, and I found more than I expected.
The comparison
React doesn't use ==
or ===
operators, it uses the Object.is()
method. This method provides the SameValue
algorithm since ES2015.
We all know the difference between Abstract Equality Comparison (==
) and Strict Equality Comparison (===
), but what comes with this new comparison?
💡 You can quickly check the differences between these equality algorithms in MDN.
We can affirm that the differences between ===
and Object.is
are:
-
+0
,-0
and0
result in the same value for===
, but different forObject.is
. «And that's a point tois
for being mathematically correct.» ✅ -
NaN === NaN
isfalse
for===
😒, buttrue
for the SameValue algorithm. «Another point toObject.is
.»
I think now it's clearer why React choses a little-known comparison method.
Show me the code
If you're a developer, I guess you want to see where is the code for Object.is
😁. The answer is in a function called areHookInputsEqual
in the ReactFiberHooks.new.js
file: https://github.com/facebook/react/blob/v18.1.0/packages/react-reconciler/src/ReactFiberHooks.new.js#L323.
💡 I used the latest tag because the code changes continuously.
It's cool to see how this check is completely ignored if you're in a hot reload process, and how the checks for the programmer are removed in the production
build of React.
Conclusion
IMO the most important issue here is that React doesn't make a deep comparison between objects, it only checks if they're the same object.
💡 If you don't know what this means check this Redux page about the benefits of immutability.
🧠 Remember that an object variable is just a memory reference (pointer) to where the object is, that's what ===
and Object.is
use when you compare two objects.
I hope you enjoyed this dive into the React's source code. 🤿