Interview Q&A / React

IntermediateIn-depth2 min readUpdated 30 Sept 2026

When should you use useEffect, and when should you avoid it?

SHORT ANSWER

Use useEffect to sync your component with something outside React, such as a network request, a subscription or a browser API. Avoid it for work you can do during rendering or inside an event handler.

Explain it simply

Rendering in React should be like a recipe: same ingredients (props and state) always give the same dish (JSX). An effect is for things that are not part of the dish, such as ringing the doorbell (talking to a server), opening a window (a browser API) or subscribing to a newsletter (a WebSocket). useEffect says: "after you show this on screen, go and sync with the outside world".

If something can be worked out from props or state while rendering, it does not need an effect. If something happens because the user clicked a button, it belongs in the click handler.

Example

jsx
function ChatRoom({ roomId }) {
  const [messages, setMessages] = useState([]);

  // Good use: keep a connection in sync with roomId
  useEffect(() => {
    const connection = connect(roomId);
    connection.on("message", (m) => setMessages((list) => [...list, m]));
    return () => connection.disconnect(); // clean up when roomId changes
  }, [roomId]);

  // No effect needed: derive during render
  const unread = messages.filter((m) => !m.read).length;

  return <p>{unread} unread</p>;
}

How it works

React runs the effect after the screen updates. When a value in the dependency array changes, React first runs the cleanup function from the previous effect and then runs the effect again. In development, Strict Mode runs effects twice on mount to help you catch missing cleanups.

Real-world use

  • Fetching data when an id changes, with a cleanup that ignores stale responses.
  • Subscribing to window resize, online/offline status or a WebSocket.
  • Integrating non-React widgets like maps or charts.

Common mistakes

  • Copying props into state with an effect ("derived state"). Calculate it during render instead, or use useMemo if it is expensive.
  • Handling user actions in an effect by watching a flag. Put that logic in the event handler.
  • Forgetting cleanup, which leaves duplicate subscriptions or timers.
  • Leaving out dependencies to "stop loops". Fix the logic instead; missing dependencies cause stale values.

What to say in the interview

"useEffect is for synchronising a component with an external system, like a subscription, a timer or a network request, and it should return a cleanup. I avoid effects for derived data, which I compute during render, and for user actions, which go in event handlers. I keep the dependency array honest, and if an effect runs too often I restructure the code instead of hiding dependencies."

Follow-up questions

  • Why does my effect run twice in development?
  • How do you avoid race conditions when fetching in an effect?
  • What is the difference between useEffect and useLayoutEffect?

#hooks#effects#state

Related questions

Practise more React questions

Test your recall with short answers, then return to the detailed explanations when you need context.

Open React quick answers →

Get new questions like this by email

One short email when something new and useful lands. No spam, unsubscribe in one tap.

By subscribing you agree to the Privacy Policy.