Let's say I have a variable that depends on a prop, and I declare it in a simple way:
const isLeapYear = year % 4 === 0; // year is a prop
Now, let's imagine I have a complex function, and I "memorize" its result using useMemo:
const result = useMemo(() => console.log('complex function', isLeapYear), [isLeapYear]);
So here’s my question: Will result be recalculated every time just like isLeapYear, since isLeapYear changes with each render? Would it be a better idea to also declare isLeapYear using useMemo?
since isLeapYear changes with each render
I don't see why it would change on every render. If you mean it's a newly-defined variable that's true, but useMemo
compares the old and new values with Object.is (similar to ===
), so all that matters is if the values are the same.
If isLeapYear
is, say, true on one render and true on the next, then the useMemo
for result will not run. Only if it toggles from true to false or vice versa will the memoization break.
Now, if you have an object in a dependency array, then you may need to memoize that object so that it's the same object reference. But primitives like booleans don't need this
const example = { isLeapYear: year % 4 === 0 };
const result = useMemo(
() => /* ... some calculation using example */,
[example] // <--- Problem! example will be a new object on every render.
)
The above code will break the memoization on ever render. The objects may have the same contents, but they are different objects. If all you're using is the isLeapYear
part you can change your dependency array to [example.isLeapYear]
. But if the whole object is needed, you'll need to memoize it.
const example = useMemo(
() => ({ isLeapYear: year % 4 === 0 }),
[year]
)
const result = useMemo(
() => /* ... some calculation using example */,
[example]
)