Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does it make sense to memoize a toggle function with useCallback?

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 by Expandable.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?

like image 569
Jordi Nebot Avatar asked Sep 17 '25 18:09

Jordi Nebot


1 Answers

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.

like image 63
Yousaf Avatar answered Sep 19 '25 07:09

Yousaf