- Home
- /
- Tutorials
- /
- React Tutorial
- /
- useEffect Explained
Effects and Refs
useEffect Explained
An effect is for reaching outside React - a network request, a subscription, a timer, the document title. If the code only computes a value, it does not belong in one.
What an effect is for
React renders your component and updates the DOM. Anything else the component needs to do - talk to a server, start a timer, listen to the window - happens after that, and useEffect is where it goes.
Running after render
jsx
function Title() {
const [count, setCount] = React.useState(0)
React.useEffect(() => {
// Runs after React has updated the DOM.
document.title = `Count: ${count}`
})
return (
<div>
<p>Count: {count}</p>
<p style={{ color: "#64748b" }}>The browser tab title follows this number.</p>
<button onClick={() => setCount(count + 1)}>Add</button>
</div>
)
}
const root = ReactDOM.createRoot(document.getElementById("root"))
root.render(<Title />)Most code is not an effect
This is the most common misuse. If a value can be calculated from props or state, calculate it during render. Putting it in an effect adds a second render, a chance to be out of date, and nothing else.
Derived, not effected
jsx
function Cart() {
const [items, setItems] = React.useState([2, 5])
// Wrong: an effect and extra state to hold something derivable.
// const [total, setTotal] = useState(0)
// useEffect(() => { setTotal(items.reduce((a, b) => a + b, 0)) }, [items])
// Right: just compute it.
const total = items.reduce((sum, n) => sum + n, 0)
return (
<div>
<p>Items: {items.join(", ")} — total {total}</p>
<button onClick={() => setItems([...items, 3])}>Add 3</button>
</div>
)
}
const root = ReactDOM.createRoot(document.getElementById("root"))
root.render(<Cart />)The commented-out version works, but renders twice for every change and can display a stale total for one frame. Deriving is simpler and always correct.
What genuinely needs one
- Fetching data from a server.
- Subscribing to something - a socket, an event listener, a store.
- Timers:
setIntervalandsetTimeout. - Manually touching the DOM outside React's tree, like the document title.
- Logging or analytics tied to something appearing.
If your effect does not appear on that list, ask what it is really for. An effect that only calls a setter based on props is usually a derived value in disguise.
It runs after paint
The user sees the rendered output first, then the effect runs. That is deliberate - it keeps rendering fast - but it means an effect that sets state causes a visible second render. Another reason not to use one for values you could compute directly.
