I'm following an Advanced React Patterns with Hooks online course and there's this early example in which they create an Expandable component (say the classic accordion or collapsible panels) with the following API:
<Expandable>
<Expandable.Header>This is the header</Expandable.Header>
<Expandable.Body>This is the content</Expandable.Body>
</Expandable>
And they're using Context to pass the state expanded
to Expandable's children. So far so good:
import React, { createContext, useState } from 'react'
const ExpandableContext = createContext()
const { Provider } = ExpandableContext
const Expandable = ({children}) => {
const [expanded, setExpanded] = useState(false)
const toggle = setExpanded(prevExpanded => !prevExpanded)
return <Provider>{children}</Provider>
}
export default Expandable
But then they say:
toggle
acts as a callback function and it’ll eventually be invoked byExpandable.Header
. Let’s prevent any future performance issues by memoizing the callback
const toggle = useCallback(
() => setExpanded(prevExpanded => !prevExpanded),
[]
)
This confuses me because according to the docs useCallback
will return a memoized version of the callback that only changes if one of the dependencies has changed. But toggle doesn't have any dependencies, and still it produces a different result (setting expanded
state to true
or false
alternatively) every time.
So, what's the point of this? What am I missing?
When the state in Expandable
component will be updated, Expandable
component will re-render. This will cause the toggle
function to be re-created.
To prevent this, it is wrapped in useCallback
hook so that toggle
function is not recreated unnecessarily across re-renders.
useCallback
hook is used to memoize callbacks that are passed as props to child components. This can help avoid unnecessary execution of useEffect
hook or any other code that depends on referential identity of the callback function passed as a prop from the parent component.
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