Search code examples
reactjsreact-hooksmemoization

Should I memoize the returned object of a custom React hook?


If I used useCallback for the methods of my custom hook, should I also memoize the returned object? I would assume that it would not create a new object everytime since it's composed with memoized methods and primitives.

export const useToggle = (args: UseToggleProps) => {
    const initialState=
        args.initialState !== undefined ? args.initialState : false
    const [active, setActive] = useState(initialState)

    const toggleOff = useCallback(() => {
        setActive(false)
    }, [])

    const toggleOn = useCallback(() => {
        setActive(true)
    }, [])

    const toggle = useCallback(() => {
        setActive((active) => !active)
    }, [])

    // Should this also be memoized with useMemo?
    return {
        active,
        toggle,
        toggleOff,
        toggleOn
    }
}

Solution

  • You don't need to memoize the returned object unless you are passing the Object directly to function of useEffect in which case reference will fail

    You don't need to add an extra layer of memoization over useCallback if you use it like this:

    const Comp = () => {
       const { toggleOn, toggleOff } = useToggle();
    
       useEffect(() => {
          console.log('Something here')
       }, [toggleOn]);  
       return (
           <Child toggleOn={toggleOn} toggleOff={toggleOff} />
       )
    }
    

    However the usages like below code will need memoization of the returned object

    const Comp = () => {
       const toggle = useToggle();
    
       useEffect(() => {
          console.log('Something here')
       }, [toggle]);  
       return (
           <Child toggleHandlers={toggle} />
       )
    }