Loading...
Loading...
When we think about performance optimizations in react, one idea that comes to mind is memoization, luckily react provides two hooks one called useMemo and useCallback
useCallback is a way we can tell react to cache a functions reference in between rerenders. The useCallback hook takes a callback function and a dependency arry to indicate when the refrence should be updated.
lets say i have a form component that signs up a new user. That form has a button with a onSumbit which we have declared in the component scope, and even if the signature of that function does not change it gets recreated on evey rerender, on way we can tell react to not recreate the onSubmit handler on evey rerender is to use wrap the onSubmit handler in the useCallback hook
example: useCallbackimport { useCallback } from 'react';
function SomeComponent(() => {
// this function will be recreacted on evey rerender
const handleSubmit = (formData) => {
// some logic
};
// this will not be recreated on evey rerender, React will use a cached reference, unless we update our `handleSubmit` since its a dependency of the useCallback
cons someOtherHandler = useCallback(handleSubmit, [handleSubmit])
return (
<form onSubmit={handleSubmit}>
</form>
)
});
In The example above the handleSubmit will be recreated on evey rerender of the component but someOtherHandler will be refrenced unless something in the dependency arry is updated.
example: useMemoimport { useMemo } from 'react';
function SomeComponent(() => {
// this function will be recreacted on evey rerender
const handleSubmit = (formData) => {
// some logic
};
// this will not be recreated on evey rerender, React will use a cached reference, unless we update our `handleSubmit` since its a dependency of the useMemo
cons someOtherHandler = useMemo(() => handleSubmit, [handleSubmit])
return (
<form onSubmit={handleSubmit}>
</form>
)
});
now you might be thinking well both the expamles above look similar so what is the difference between them?
Both useCallback and useMemo have a similar api and both are intended to cache the result of the hook they are being assignd to.
in useCallback, the callback function that is passed as the first argument is what gets cached, in useMemo whatever gets returned from the callback function is what gets cached.
useCallback is recomended to be used to cache function refrence not its result ex (callbacks).
useMemo is recomended to be used to save the result of expensive functions
function PostsList({ todos, tab, theme }) {
// this declaration will be recreated on every subsequent rerender unless we wrap it in a useCallback
const filterPosts = () => {}, [posts]
// this declaration will be cached on every subsequent rerender.
const filteredPostsCallback = useCallback(() => {}, [posts]);
}
function PostsList({ todos, tab, theme }) {
// if we have a lot of posts filtering them on rerender can be taxing and expensive.
const filteredPostsMemo = useMemo(() => filterPosts(posts), [posts]);
}
in short useCallback will return the function that is passed with out invoking the function and useMemo with invoke the function that is passed and cached its return value and not the declaration.
in both useCallback and useMemo react will call your function during the initial render. On any subsequent renders, react will return the same value again if the dependencies have not changed since the previous render. Both use Object.is under the hood to compare the dependencies in between renders