Writing

useEffect

Oct 3, 2026 · 2 min read · react · hooks

desert night from ascii.rest

useEffect lets a component subscribe to something React does not own. The render stays pure, and both the setup and the cleanup belong in the effect. The old habit of setting state during render waits until after the browser paints.

A cleanup is required when the effect opens a socket, a timer, or a subscription. The dependency array is the second argument. For a room that connects once, that array is empty: []. The reference is useEffect, and the same page also appears as a bare address:

https://react.dev/reference/react/useEffect

What the effect is for

An effect synchronizes the component with an external system.

  • open a connection
  • keep it in step with props
    • compare the room id
      • reconnect when the id changes
  • close it from the returned function

React's order of work is fixed:

  1. React renders the component.
  2. The browser paints.
  3. The effect runs.
  • return a cleanup
  • leave the socket open after unmount

Effects are an escape hatch. If the value can be calculated during render, it does not belong in an effect.


Timing

HookRunsUse it for
useEffectafter paintsubscriptions, fetching, logging
useLayoutEffectbefore paintmeasuring the DOM

A connection

Room.jsx
import { useEffect } from "react";

export function Room({ roomId }) {
  useEffect(() => {
    const connection = createConnection(roomId);
    connection.connect();
    return () => connection.disconnect();
  }, [roomId]);
}

The same steps, without a language tag:

text
connect
disconnect
One photograph of a room
The only JPEG in the gallery

The dependency list

If the effect reads roomId, then roomId belongs in the array. React runs the cleanup before the next effect, and once more on unmount.1

Markup inside the paragraph

Water is H2O, and an effect that runs on every change grows like x2.

MDX that this page does not compile

This file is .mdx. The CMS stores the body as Markdown, so an import, an expression, and a component stay as text:

import { useEffect } from "react";

The doubled count is {count * 2}.

{/* cleanup belongs next to setup */}

mdx
<Callout>Do not start a subscription during render.</Callout>

Footnotes

  1. The cleanup from the previous render runs before the next effect, then again when the component unmounts. ↩

Shishir JhaDeveloper · Creator · Learner

Newsletter signup will open soon.