REACTJS • LESSON 18 OF 36

Life cycle Hooks

Synchronize with timers and requests, and clean up after them.

Read the explanation, run the worked example, then complete the matching Examples and Assignments tabs. Your original materials remain available alongside these notes.

Understand the idea

Rendering calculates UI. An effect handles an external system such as a timer or request after a commit. Return cleanup that reverses the setup. With dependencies, React cleans up the previous effect before setting up the next version when those values change. Development Strict Mode intentionally exercises setup and cleanup again.

For your clock, an interval updates state and cleanup clears it. For a countries request, represent loading, success and error separately, check response.ok, and cancel an obsolete request. A click-specific alert belongs in the click handler; using an effect only to notice that a click changed state introduces unnecessary indirection.

Render with current state ↓ Commit UI ↓ Effect setup ↓ Cleanup before replacement
Trace the values through each step before changing the code.

Run the example

Use a separate React practice project with a Node.js version supported by Vite. Create it once with these commands, then use its development URL. Do not paste this into the Edupoly website’s own source files.

npm create vite@latest react-practice -- --template react
cd react-practice
npm install
npm run dev

Replace src/App.jsx with the following complete example. Keep Vite’s generated src/main.jsx entry point.

src/App.jsx

import { useEffect, useState } from 'react';
export default function App() {
  const [now, setNow] = useState(() => new Date());
  useEffect(() => {
    const timer = setInterval(() => setNow(new Date()), 1000);
    return () => clearInterval(timer);
  }, []);
  return <time>{now.toLocaleTimeString()}</time>;
}

Expected result

The clock advances every second. Removing the component clears its interval.

Alternative worked example — replace src/App.jsx

For a local request fixture, create public/countries.json containing the following JSON. You can later replace the URL with your Countries API and adapt its response format.

[{"id":"IN","name":"India"},{"id":"JP","name":"Japan"}]
import { useEffect, useState } from 'react';
export default function Countries({url = '/countries.json'}) {
  const [result, setResult] = useState({loading: true, rows: [], error: ''});
  useEffect(() => {
    const controller = new AbortController();
    let active = true;
    setResult({loading: true, rows: [], error: ''});
    async function load() {
      try {
        const response = await fetch(url, {signal: controller.signal, headers: {Accept: 'application/json'}});
        if (!response.ok) throw new Error(`Request failed: ${response.status}`);
        const rows = await response.json();
        if (!Array.isArray(rows)) throw new Error('Expected an array');
        if (active) setResult({loading: false, rows, error: ''});
      } catch (error) {
        if (active && error.name !== 'AbortError') setResult({loading: false, rows: [], error: error.message});
      }
    }
    load();
    return () => { active = false; controller.abort(); };
  }, [url]);
  if (result.loading) return <p>Loading countries…</p>;
  if (result.error) return <p role="alert">{result.error}</p>;
  return <ul>{result.rows.map(row => <li key={row.id}>{row.name}</li>)}</ul>;
}

Apply this to your assignments

Complete the clock and increment exercises, then use the request pattern below for your Countries API. Provide your own endpoint with an array of {id,name} records or adapt the response mapping. Test offline mode and a failed status.

Your existing examples

  • UseEffect with DepArray Refactoring Component
  • API Calls with headers using fetch inside useEffect hook

Open the Examples tab to run or inspect these supplied projects. Their original links are preserved.

Open Assignments for your complete original worksheet. Use the assignment workspace link to submit completed work.

Common mistakes

Do not make the effect callback itself async: it must return cleanup, not a promise. Never put private API keys in browser code.

Check your understanding

  1. Predict the output before running the example, then compare it with the result panel.
  2. Explain which value each expression reads and which action changes it.
  3. Try the boundary cases listed in the practice task and record what you observe.
  4. Rebuild one matching assignment without copying, then compare behavior with the original example.

Reference

Official documentation for this topic · Vite setup requirements