Best Practices for Handling Side Effects in React

When working with React, handling side effects correctly can make or break your component’s performance, readability, and predictability. Side effects—like data fetching, subscriptions, or DOM manipulations—shouldn’t be sprinkled all over your codebase like confetti. Here’s a deep dive into the best practices every serious React dev should follow when dealing with side effects. ⚠️ First, What Are Side Effects in React? Side effects are operations that affect something outside the scope of the current function being executed. In React, they can include: Fetching data from APIs Manually modifying the DOM Subscribing to WebSocket or event listeners Setting timeouts or intervals Logging or analytics tracking These are not part of the component’s render output and must be handled outside the render phase. ✅ 1. Use useEffect for Declarative Side Effects React's useEffect hook is the official home for most side effects in functional components. useEffect(() => { const fetchData = async () => { const res = await fetch("/api/data"); const data = await res.json(); setData(data); }; fetchData(); }, []); Best practice: Use the dependency array correctly. It should contain everything your effect depends on. ✅ 2. Separate Concerns — Don't Cram Everything Into One Effect Avoid the “God effect” trap where one useEffect tries to do it all. Split effects by purpose: data fetching, subscriptions, cleanup logic, etc. useEffect(() => { // Handles window resize const handleResize = () => setWidth(window.innerWidth); window.addEventListener("resize", handleResize); return () => window.removeEventListener("resize", handleResize); }, []); useEffect(() => { // Fetch data separately }, []); ✅ 3. Always Clean Up Subscriptions and Timeouts If you don’t clean up, you’ll leak memory and trigger bugs during unmounting or re-renders. useEffect(() => { const timer = setTimeout(() => { console.log("Delayed log"); }, 1000); return () => clearTimeout(timer); }, []); ✅ 4. Avoid Side Effects During Rendering Never call fetch(), setTimeout(), or manipulate the DOM directly during render.

May 14, 2025 - 06:28
 0
Best Practices for Handling Side Effects in React

When working with React, handling side effects correctly can make or break your component’s performance, readability, and predictability. Side effects—like data fetching, subscriptions, or DOM manipulations—shouldn’t be sprinkled all over your codebase like confetti.

Here’s a deep dive into the best practices every serious React dev should follow when dealing with side effects.

⚠️ First, What Are Side Effects in React?

Side effects are operations that affect something outside the scope of the current function being executed. In React, they can include:

  • Fetching data from APIs
  • Manually modifying the DOM
  • Subscribing to WebSocket or event listeners
  • Setting timeouts or intervals
  • Logging or analytics tracking

These are not part of the component’s render output and must be handled outside the render phase.

✅ 1. Use useEffect for Declarative Side Effects

React's useEffect hook is the official home for most side effects in functional components.

useEffect(() => {
  const fetchData = async () => {
    const res = await fetch("/api/data");
    const data = await res.json();
    setData(data);
  };

  fetchData();
}, []);

Best practice:
Use the dependency array correctly. It should contain everything your effect depends on.

✅ 2. Separate Concerns — Don't Cram Everything Into One Effect

Avoid the “God effect” trap where one useEffect tries to do it all. Split effects by purpose: data fetching, subscriptions, cleanup logic, etc.

useEffect(() => {
  // Handles window resize
  const handleResize = () => setWidth(window.innerWidth);
  window.addEventListener("resize", handleResize);

  return () => window.removeEventListener("resize", handleResize);
}, []);

useEffect(() => {
  // Fetch data separately
}, []);

✅ 3. Always Clean Up Subscriptions and Timeouts

If you don’t clean up, you’ll leak memory and trigger bugs during unmounting or re-renders.

useEffect(() => {
  const timer = setTimeout(() => {
    console.log("Delayed log");
  }, 1000);

  return () => clearTimeout(timer);
}, []);

✅ 4. Avoid Side Effects During Rendering

Never call fetch(), setTimeout(), or manipulate the DOM directly during render.