Skip to content

React Tutorial React Hooks

You Might Not Need an Effect: Common useEffect Mistakes

Lesson 64 of 156 2 min read By Deepak Paswan Updated Oct 10, 2026

Runnable lesson · press Try it on the examples to edit and run them here.

Effects are an escape hatch to talk to the world outside React. Many bugs come from using them for jobs React handles better. This lesson shows the five most common cases and the simpler replacement for each.

1. Calculating a value from props or state

Instead of an effect that copies a result into state:

App.jsx
JSX
const [fullName, setFullName] = useState("");
useEffect(() => {
  setFullName(first + " " + last);
}, [first, last]);

This renders twice for every change (once with the old fullName, once after the effect), and fullName can briefly be wrong. Just calculate it:

App.jsx
JSX
function App() {
  const [first, setFirst] = React.useState("Ada");
  const [last, setLast] = React.useState("Lovelace");
  const fullName = first + " " + last; // calculated during render

  return (
    <div>
      <input aria-label="First" value={first} onChange={(e) => setFirst(e.target.value)} />
      <input aria-label="Last" value={last} onChange={(e) => setLast(e.target.value)} />
      <p>{fullName}</p>
    </div>
  );
}

2. Responding to a user event

If something happens because the user clicked, put the code in the click handler. An effect cannot tell why a value changed, so it may run at the wrong time.

App.jsx
JSX
// Instead of this:
useEffect(() => {
  if (submitted) post("/api/save", data);
}, [submitted]);

// Do this:
function handleSubmit() {
  post("/api/save", data);
}

Use effects for things that should happen because the component is on the screen (a chat connection), not because the user did something.

3. Resetting state when a prop changes

App.jsx
JSX
// Instead of this:
useEffect(() => { setComment(""); }, [postId]);

Give the component a key, so React resets everything cleanly; see useState in Depth:

App.jsx
JSX
<CommentBox key={postId} postId={postId} />

4. Chains of effects

An effect that sets state, which triggers another effect that sets more state, is slow and fragile. Calculate what you can during render, and do the rest in the event handler that started it.

5. Notifying a parent after state changes

App.jsx
JSX
// Instead of an effect calling onChange(value) after state updates...
useEffect(() => { onChange(isOn); }, [isOn]);

// ...call it in the same event handler that changes the state:
function handleClick() {
  setIsOn(!isOn);
  onChange(!isOn);
}

Even better: let the parent own the state (lifting state up), so the child has nothing to notify. See Lifting State Up.

When an effect IS right

Good useWhy an effect
Connect to a chat server while the component is shownIt must start on mount and stop on unmount
Add and remove a window event listenerOutside system
Control a third-party widget such as a mapOutside system
Send an analytics event because a page was displayedThe reason is “it appeared”, not a click
Fetch data when a component showsA basic version; libraries do it better

A quick test

Ask: “Why does this code need to run?”

  • Because the user did something → event handler.
  • Because this component is on the screen → effect.
  • Because some data changed and I need a new value from it → calculate during render.

Key points

  • Compute derived values during render, not in effects.
  • Handle user actions in event handlers.
  • Use effects only to synchronise with something outside React.