DEV Community

Wei Gao
Wei Gao

Posted on

6 2

Properly Include Component Function from `useEffect` and `useCallback` Dependency List

I was working on Slots (letting a portal component render into a potentially not mounted portal home) when initially I was violating a hooks rule. Namely, I did not include the setSlot function I called within the useCallback body inside its dependency list.

export const SlotHome = ({ slotName, className }) => {
  const [, setSlot] = useSlot(slotName)
  const ref = React.useCallback(node => {
    // we're lying to hooks because we're using setSlot without including it in the deps list
    setSlot(node)
  }, [])
  return <div className={className} ref={ref} />
}

But if I do include it, the function is different every time the component render is called and therefore would re-render like a maniac. Without including it, the implementation still works, but we're lying to hooks and it is strongly advised against.

This made me finally decided (cuz it says it's a 49-min read) to read Dan Abramov's article, A Complete Guide to useEffect and decided to properly figure this out. Here are some key takeaways:

  • class components mutate state
  • functional components + hooks retain the proper closure behavior (always use closed variable, no mutating crap)
  • 3 ways to optimize dependency list
    • remove unnecessary use of params in component lifecycle scope
    • use reducer
    • memoize functions with useCallback

The highlighted takeaway was what solved this problem. The idea is to tell hooks that the function won't change unless what we specify in that useCallback's dependency list change.

const [, setSlot] = useSlot(slotName)
// specify that setSlotMemo won't change unless slotName changes
const setSlotMemo = React.useCallback(setSlot, [slotName])

// now ref is safe to include setSlotMemo in its deps list
const ref = React.useCallback(
  node => {
    setSlotMemo(node)
  },
  [setSlotMemo]
)

Once again Dan's article covers a complete guide to properly use useEffect (which extends to useCallback because they share the same signature).

Relevant links

Speedy emails, satisfied customers

Postmark Image

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay