Sitemap
Rahulspagidimarri

Rahulspagidimarri

React useEffect

2 min readSep 4, 2026

--

Press enter or click to view image in full size

useEffect is used when your React component needs to synchronize with something outside React.

Examples of external systems:

  • Timers
  • WebSocket connections
  • Browser event listeners
  • API subscriptions
  • Third-party libraries

A simple rule:

If there is no external system to synchronize with, you probably do not need useEffect.

Basic syntax

useEffect(() => {
// Synchronize with something outside React
  return () => {
// Clean up if needed
};
}, [dependencies]);

An Effect runs after React renders the component.

useEffect(() => {
console.log("Room changed");
}, [roomId]);

This runs:

  • When the component first appears
  • Whenever roomId changes

Dependency array patterns

useEffect(() => {
// Runs after every render
});
useEffect(() => {
// Runs after the component first appears
}, []);
useEffect(() => {
// Runs after first render and whenever userId changes
}, [userId]);

Effects are not for user actions

Use event handlers for things caused by the user, such as clicks, typing, and form submissions.

function Counter() {
const [count, setCount] = useState(0);
  function handleClick() {
setCount(count + 1);
}
return <button onClick={handleClick}>{count}</button>;
}

There is no need for an Effect here.

Get Rahulspagidimarri’s stories in your inbox

Join Medium for free to get updates from this writer.

A good distinction is:

  • Component appears or updates → useEffect
  • User clicks, types, or submits → event handler

Avoid direct DOM manipulation when React can handle it

React gives us built-in event props such as onChange.

import { useState } from "react";
export default function App() {
const [input, setInput] = useState("");
function handleInput(event) {
setInput(event.target.value);
}
return (
<>
<input value={input} onChange={handleInput} />
<p>{input}</p>
</>
);
}

Usually, avoid manually using:

document.getElementById(...)

React event handlers are cleaner and automatically managed.

Clean up what you start

If an Effect starts a timer, listener, or connection, clean it up.

useEffect(() => {
const intervalId = setInterval(() => {
console.log("Running...");
}, 1000);
  return () => {
clearInterval(intervalId);
};
}, []);

Cleanup runs when:

  • The component is removed from the UI
  • Dependencies change before the Effect runs again

The three questions to ask

Before writing an Effect, ask:

Example:

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

Final rule

Render for UI.
Event handlers for user actions.
Effects for external synchronization.

Avoid using Effects to calculate values, reset state, or make components communicate. In many cases, derived values, React keys, or lifting state to a parent are cleaner solutions.

--

--