When to useEffect

There's plenty articles on when to useEffect, but none of them could provide a TLDR for devs new to react.

What is useEffect?

useEffect was introduced as one of the core hooks in react 16.8. It was described as a way to run "side-effects" within your components. It serves the same purpose as livecycle hooks in other frameworks (and react, prior to hooks).

You’ve likely performed data fetching, subscriptions, or manually changing the DOM from React components before. We call these operations “side effects” (or “effects” for short) because they can affect other components and can’t be done during rendering.
source: react docs

Kent C Dodds describes it as "a way to sync the state of react, with the state of the world". "World" being anything OUTSIDE OF REACT. If you take home anything from this article, let it be this sentence.

useEffect = "a way to sync the state of react, with something outside of react"

When you shouldn't useEffect

To sync props, state or anything else that is already inside of react with another state.

// ❌ bad: we're syncing props with state.
// there's no "state of the world" to sync with, so useEffect should not be used here
function MyComponent({ todos }) {
  const [filteredTodos, setFilteredTodos] = useState([]);
 
  useEffect(() => {
    const data = todos.filter(...);
    setFilteredTodos(data)
  }, [todos]);
 
  return <div>...</div>;
}
 
// ✅ better: no extra state + no useEffect
function MyComponent({ todos }) {
  const filteredTodos = todos.filter(...);
 
  return <div>...</div>;
}

Anything named "filteredX", "selectedX", should most likely not be synced with useEffect.

When you should useEffect

To sync the state of react with the state of the world.

  • to subscribe to native dom events, or gestures: eg. window.addEventListener('mousemove') - (window = world)
  • to sync state with native browser apis: eg: userMedia, navigator - (navigator = world)
  • subscribe to websockets (instance of new WebSocket("ws://localhost:3000") = world)
  • call apis (you need to handle deduping etc, so its better to use a library like react-query for this) - (api endpoints = world)
  • to interact / sync state with things that live outside of react (global objects like document, window, or vendor stuff like Autodesks NOP_VIEWER)

Resources

If you want to dive in deeper with useEffect check out these resources