3
\$\begingroup\$

I'm toggling a state when the browser is resized:

const [expanded, setExpanded] = useState(true)
useEffect(() => {
  const listener = () => {
    if (document.documentElement.clientWidth > 1024) return
    setExpanded(false)
  }
  window.addEventListener('resize', listener)
  return () => window.removeEventListener('resize', listener)
}, [])

I've the react-hooks/exhaustive-deps rule enabled so ESLint complains:

React Hook useEffect has a missing dependency: 'setExpanded'. Either include it or remove the dependency array

How should I rewrite this? Or should I simply silence the ESLint warning?

\$\endgroup\$
4
\$\begingroup\$

Short answer:

You can include setExpanded in the dependency array.

Long answer:

The function passed to useEffect will fire only when at least one of the dependencies changes:

useEffect(() => {
  // runs
  // - on mount
  // - on every render
})

useEffect(() => {
  // runs
  // - on mount only
}, [])

useEffect(() => {
  // runs
  // - on mount
  // - on renders where varA and/or varB change
}, [varA, varB])

You should avoid passing objects as dependencies, because they may trigger unnecessary re-renders. If varA is an object created on every render, it may have the same value but it won't be the same object, so it will be treated as change and fire up the useEffect. See the example below:

const varA = { a : 1 }
const varB = { a : 1 }

varA === varB // false

However, sometimes, certain objects are guaranteed to not produce this behaviour, and this is the case of the setState() function. According to the React Hooks API docs:

Note: React guarantees that setState function identity is stable and won’t change on re-renders.

This means that you can include it in the useEffect dependencies with no problem.

\$\endgroup\$
  • \$\begingroup\$ Thanks for the answer. Is this the best practice to do? Didn't see anything like this in the React docs. \$\endgroup\$ – Elmo Jan 21 at 9:59
  • \$\begingroup\$ I would pass setExpanded as a dependency since according to the docs it's "free" for you to do so, but I think it would also be acceptable to pass an empty dependency array and silence the warning. \$\endgroup\$ – Pablo Jan 21 at 10:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.