When developing a product with React, if you write components and use Hooks a lot without paying special attention, the overall operation may become slow, even if the project size is not large.
It's important to understand the role of Hooks and to use them in the right places. In this article, we summarize the explanations of some of the Hooks provided by React.
📌 useMemo
useMemo
is a hook to save (memoize) the result of a function and retrieve the value when it is called again. This eliminates unnecessary recalculation and improves performance.
const value = useMemo(() => {
// doSomething
}, [])
It's effective when used for functions with high computational cost. Also, unlike useCallback
, it is not a Hook that memoizes the function itself. Also, by passing variables as the second argument (deps), the function can be called to recalculate when thosae values are changed.
👎 The following code calls a function each time a component is rendered.
const Component = () => {
const doSomething = () => {
// A function with a with high computational cost
}
return (
<div>{doSomething()}</div>
)
}
👍 The following code calls the function only when the component is rendered for the first time or when the value passed to deps is updated.
import { useMemo } from 'react'
const Component = () => {
const doSomething = useMemo(() => {
// A function with a with high computational cost
}, [])
return (
<div>{doSomething}</div>
)
}
📌 useCallback
useCallback
memoizes the function itself. It is mainly used for functions defined inside components such as handlers.
All functions defined inside a component are regenerated when the component is re-rendered (e.g., when the props value is updated or the parent component is re-rendered).
Basically, there is no need to regenerate functions on every rendering pass, so the use of useCallback
improves performance.
⚡ Example
For example, suppose you have the following code In this code, re-rendering of the Child component will occur at the following times:
- When setValue is called by some action
- When someData is updated by some action
Assuming that this action can occur frequently, each time this happens, the old function is discarded and a new function is created and bound to the button. The accumulation of such components will needlessly degrade performance.
const Parent = () => {
const [value, setValue] = useState(0)
return (
<>
<div>{value}</div>
<Child data={someData} />
</>
)
}
const Child = (props) => {
const handleClick = () => {
// doSomething
}
return (
<>
<div>{props.data}</div>
<button onClick={handleClick}></button>
</>
)
}
In this case, you can wrap the handleClick function with useCallback
.
import { useCallback } from 'react'
// ...
const Child = (props) => {
const handleClick = useCallback(() => {
// doSomething
})
// ...
}
⚡ React.memo
In addition, re-rendering of child components, which occurs when rendering parent components, can be avoided by using React.memo
.
import { memo } from 'react'
// ...
const Child = memo((props) => {
// ...
})
Components wrapped in React.memo
will return memoized values as long as the props do not change. This reduces unnecessary re-rendering.
Top comments (0)