#react #tutorial #intermediate

Day 4: Side Effects & Lifecycle

Day 4: Side Effects & Lifecycle

We know how to render UI (return JSX) and handle user interaction (useState). But what about things that happen outside the render flow? Like fetching data from an API, setting up a timer, or manually changing the document title?

These are called Side Effects, and we handle them with the useEffect hook.

The useEffect Hook

useEffect lets you perform side effects in functional components. It runs after the render.

import { useState, useEffect } from 'react';

function Timer() {
  const [count, setCount] = useState(0);

  // This runs after EVERY render
  useEffect(() => {
    document.title = `Count: ${count}`;
  });

  return <button onClick={() => setCount(count + 1)}>Click me</button>;
}

The Dependency Array

You rarely want an effect to run after every single render. We can control when it runs using the Dependency Array (the second argument).

1. Run Once (On Mount)

Passing an empty array [] tells React: “This effect doesn’t depend on any props or state, so run it ONLY once when the component first appears.”

useEffect(() => {
  console.log('Component Mounted!');
}, []); // Empty array

This is perfect for API calls.

2. Run When Specific Data Changes

Pass variables into the array. The effect runs only when those variables change.

useEffect(() => {
  console.log('Count changed to:', count);
}, [count]); // Runs only when 'count' changes

Data Fetching Example

Let’s fetch some users from a fake API.

function UserList() {
  const [users, setUsers] = useState([]);

  useEffect(() => {
    // Define async function inside or use .then syntax
    async function fetchUsers() {
      const response = await fetch('https://jsonplaceholder.typicode.com/users');
      const data = await response.json();
      setUsers(data);
    }

    fetchUsers();
  }, []); // Run once on mount

  return (
    <ul>
      {users.map(user => <li key={user.id}>{user.name}</li>)}
    </ul>
  );
}

Cleanup Function

Sometimes an effect needs to clean up after itself—like clearing a timer or removing an event listener. You do this by returning a function from useEffect.

useEffect(() => {
  const interval = setInterval(() => {
    console.log('Tick');
  }, 1000);

  // Cleanup function runs when component unmounts
  return () => clearInterval(interval);
}, []);

If you don’t clean up, you might get memory leaks or weird bugs when the component disappears.


Homework for Day 4:

  1. Create a component that fetches a random joke from https://api.chucknorris.io/jokes/random.
  2. Display the joke.
  3. Add a “Get New Joke” button that re-fetches data (hint: you might don’t even need useEffect for the button click, but try triggering the effect by changing a state variable!).

Tomorrow, we organize our data with Lists & Keys!