This is common explaination about useMemo hook in React.js
useMemo(compute, dependencies) invokes compute, memoizes the calculation result, and returns it to the component.
If during next renderings the dependencies don’t change, then useMemo() doesn’t invoke compute but returns the memoized value.
- Dmitri Pavlutin
However, I saw the example of useMemo hooks that returns an array like this below.
React.useMemo(() => [1, 2, 3], []);
As you can see, useMemo returns an array which is considered as an object in Javascript.
This is confusing. I thought usage of useMemo hook is for memoizing calculated value.
So I did a little test to figure out how useMemo with object works
const Child = React.memo(({ obj }) => {
console.log('this is child component')
return <div>Child Component</div>
})
const App = () => {
const [toggle, setToggle] = React.useState(false)
const memoObj = React.useMemo(() => { return { bar: 'foo' } }, [])
return (
<div>
<button onClick={() => setToggle(!toggle)}>test</button>
<Child obj={memoObj} />
</div>
);
}
When memoObj is not wrapped by useMemo, whenever I click test button, I can see the message from Child component in console.
On the other hand, when memoObj is wrapped by the hook, the message shows up only when Child component rendered first time.
Does it mean that useMemo not only memoize calculated value but also reference of an object as well?
Does it mean that useMemo not only memoize calculated value but also reference of an object as well?
Yes of course and does not re-render the memoized component until is necessary to re-render it (like something has changed).
BUT you have to keep in mind that:
By default it will only shallowly compare complex objects in the props object.
So
If you want control over the comparison, you can also provide a custom comparison function as the second argument.
function MyComponent(props) {
/* render using props */
}
function areEqual(prevProps, nextProps) {
/*
return true if passing nextProps to render would return
the same result as passing prevProps to render,
otherwise return false
*/
}
export default React.memo(MyComponent, areEqual);
This is what React says.
That is true, useMemo will always keep the reference to the object from the last renders while useCallback keep the reference of function (also an object) from the last renders
Your example is also a great way to see how useMemo works!
You could also create the same example for useCallback, this will give the same behaviour
const Child = React.memo(({ obj }) => {
console.log('this is child component');
return <div>Child Component</div>;
});
const App = () => {
const [toggle, setToggle] = React.useState(false);
const useCallbackObj = React.useCallback(() => {
console.log('callback is called!');
}, []);
return (
<div>
<button onClick={() => setToggle(!toggle)}>test</button>
<Child obj={useCallbackObj} />
</div>
);
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With