You Might Not Need an Effect: Better React Patterns

Most state adjustments can happen during render or in an event handler. Learn the React patterns that replace unnecessary Effects.

6 min read

Most state adjustments do not need an Effect. If a value can be computed during render, compute it. If code runs because of a user action, keep it in the event handler.

You might not need an Effect for these common cases.

Derive data during render

A full name is two state values joined together. Storing the joined result in state creates a second source of truth that can drift. A value that depends only on existing props or state is a candidate for a plain calculation.

App.jsxApp.jsx
import { useState } from "react";
 
function NameForm() {
  const [first, setFirst] = useState("");
  const [last, setLast] = useState("");
  const fullName = `${first} ${last}`;
  return <p>{fullName}</p>;
}

fullName is recalculated on every render from the same state, so it never falls out of sync. There is no Effect, no extra render pass, and no redundant state. The same idea applies to filtered lists, totals, and any value that is a function of what you already have.

Move event logic into handlers

A purchase is caused by a click, not by the page being displayed. The request belongs in the handler.

App.jsxApp.jsx
function handleBuyClick() {
  fetch("/api/buy", { method: "POST" });
}

Putting this in an Effect would run it twice in development and again if the user navigates away and back. An event handler runs exactly when the user acts, which is the correct boundary for this logic. Two buttons can share a helper function, so the logic stays in one place without an Effect.

Reset state with a key instead of an Effect

When switching between profiles, an Effect that clears form state runs after a render with stale data. A key tells React the component is a different instance.

App.jsxApp.jsx
<Profile key={userId} userId={userId} />

When userId changes, React unmounts the old Profile and mounts a fresh one, so all of its state resets automatically. No Effect is needed. The key works for any subtree whose state belongs to one item, such as a profile, a chat thread, or a form tied to a record.

When an Effect is still right

External systems are the exception. A timer, a network request, a browser API, or a third-party widget lives outside React, so useEffect is the right tool to stay synchronized with it. The test is simple: does the work exist because the component is on screen, or because the user did something?

What to learn next

Removing Effects usually simplifies the component. Each pattern above trades an Effect for a plain calculation or a direct call.

Keeping render pure and handlers explicit is the habit that prevents most loops. When you do need one, how the dependency array works is the next concept to master.

Rune AI

Rune AI

Key Insights

  • Calculate derived values during render instead of syncing them with an Effect.
  • Keep event-specific logic in the event handler.
  • Reset state with a key prop instead of an Effect that watches a prop.
  • Reserve Effects for external systems React does not control.
RunePowered by Rune AI

Frequently Asked Questions

When can I skip an Effect?

When a value can be calculated from existing props or state during render, or when code should run in response to a specific user interaction.

How do I reset state when a prop changes?

Pass the prop as a key to an inner component. React resets the inner component's state whenever the key changes.

Are Effects ever required?

Yes. Use an Effect to synchronize with an external system such as a timer, a network request, a browser API, or a third-party widget.

Conclusion

Effects are for synchronizing with external systems, not for deriving data or responding to clicks. Compute during render and handle events in handlers, and most unnecessary Effects disappear.