ProgramGuru

useEffect: Synchronize with an External System

useEffect: Synchronize with an External System

The attendance page should put the selected class in the browser tab title. The selection belongs to React, but the tab title belongs to a browser API outside the rendered component.

An Effect is code that synchronizes a component with something outside React after a commit. useEffect declares that synchronization. It is different from calculating JSX or responding to one specific click.

  1. Understand

    Separate rendering, events and synchronization.

  2. Build

    Keep a browser title aligned with the selected class.

  3. Check

    Identify calculations that do not require an Effect.

Commit first, synchronize afterward

  1. State

    The selected class is 7A.

  2. Render and commit

    React describes and updates the class screen.

  3. Synchronize

    The Effect sets the browser tab title.

Read this relationship alongside the complete code. This diagram explains the flow; it does not execute React.

Choose the right place for the work

Rendering calculates what the interface should look like from current props and state. An event handler performs work caused by a particular interaction, such as submitting attendance. An Effect handles synchronization that must follow the component’s committed state, regardless of which interaction produced that state.

document.title is a browser property. Setting it is an externally visible side effect, so it should not happen while the component calculates its JSX. The Effect below runs after a commit and uses className to align the title. The dependency array describes the changing value used by this synchronization.

Synchronize the selected class with the tab title

The visible page initially says Class: 7A. After the commit, the tab title says Attendance 7A. Clicking Choose 7B changes state; a later commit describes 7B and its Effect aligns the title. The page itself does not need an Effect to display the class.

React · JavaScript with JSX

import { useEffect, useState } from 'react';
export default function App() {
  const [className, setClassName] = useState('7A');
  useEffect(() => {
    const previousTitle = document.title;
    document.title = 'Attendance ' + className;
    return () => { document.title = previousTitle; };
  }, [className]);
  return <main><h1>Attendance title</h1><p>Class: {className}</p>
    <button onClick={() => setClassName('7B')}>Choose 7B</button></main>;
}

Expected screen and behavior

The page initially shows Class: 7A. The browser title becomes Attendance 7A after the Effect. Choose 7B changes the page and title to 7B.

Trace state, commit and synchronization separately

React · Synchronize the selected class with the tab title

import { useEffect, useState } from 'react';
export default function App() {
  const [className, setClassName] = useState('7A');
  useEffect(() => {
    const previousTitle = document.title;
    document.title = 'Attendance ' + className;
    return () => { document.title = previousTitle; };
  }, [className]);
  return <main><h1>Attendance title</h1><p>Class: {className}</p>
    <button onClick={() => setClassName('7B')}>Choose 7B</button></main>;
}

On the first render, useState supplies 7A. React creates the described heading, paragraph and button. The Effect then saves the old title and writes Attendance 7A. Saving the previous title gives cleanup something meaningful to restore.

On a changed dependency, React runs the previous cleanup before the next setup. The next setup writes Attendance 7B. On unmount, the final cleanup restores the title it saved. This is a small demonstration where one component owns the title; a full app should coordinate title ownership centrally.

Derive a report total during rendering

Adding maths and science marks produces data, not synchronization with an outside system. Compute the total directly in the render rather than storing it in state and using an Effect to copy it. The direct calculation avoids an unnecessary extra update and cannot drift from its inputs.

A save button should save in its handler when saving is caused by that click. Moving the save into an Effect watching a boolean makes the cause harder to follow. Use an Effect when the visible component genuinely needs ongoing synchronization with an external resource.

Try the school task

React · starting example

import { useEffect, useState } from 'react';
export default function App() {
  const [className, setClassName] = useState('7A');
  useEffect(() => {
    const previousTitle = document.title;
    document.title = 'Attendance ' + className;
    return () => { document.title = previousTitle; };
  }, [className]);
  return <main><h1>Attendance title</h1><p>Class: {className}</p>
    <button onClick={() => setClassName('7B')}>Choose 7B</button></main>;
}

Keep a report title aligned with a selected student instead of a class. Show Maya initially and allow selecting Ravi. Include cleanup and the student dependency.

Worked answer

The same ownership rule applies: state controls the rendered student, and an Effect synchronizes the external tab title. Cleanup restores the previous title. No separate state is needed to remember a copied title.

React · JavaScript with JSX

import { useEffect, useState } from 'react';
export default function App() {
  const [student, setStudent] = useState('Maya');
  useEffect(() => {
    const previous = document.title;
    document.title = 'Report: ' + student;
    return () => { document.title = previous; };
  }, [student]);
  return <main><h1>Report title</h1><p>Student: {student}</p>
    <button onClick={() => setStudent('Ravi')}>Choose Ravi</button></main>;
}

Expected screen and behavior

Maya appears initially. Choose Ravi updates the page and its tab title.

Mistakes and boundaries

Effects do not run during server rendering. A server-rendered page needs the appropriate framework metadata mechanism for an initial document title rather than relying on this browser Effect.

StrictMode performs additional development checks, including an extra setup and cleanup cycle for Effects. Design reversible setup rather than relying on an exact count of calls. This example restores what it changed.

Multiple components independently writing document.title can conflict. A demo with one owner is not a complete application metadata system.

Check your reasoning

React · Synchronize the selected class with the tab title

import { useEffect, useState } from 'react';
export default function App() {
  const [className, setClassName] = useState('7A');
  useEffect(() => {
    const previousTitle = document.title;
    document.title = 'Attendance ' + className;
    return () => { document.title = previousTitle; };
  }, [className]);
  return <main><h1>Attendance title</h1><p>Class: {className}</p>
    <button onClick={() => setClassName('7B')}>Choose 7B</button></main>;
}

Choose the answer that follows the data and the interaction, then read the explanation for each alternative.

Where should a total calculated solely from current marks be produced?
Choose one answer. You can try again.

Answer and explanation

Directly during rendering from those marks.

Correct. This is a calculation, with no external system to synchronize.

Carry the idea forward

Use Effects for external synchronization after commits, handlers for interaction-caused actions and rendering for calculations. Continue with dependency reasoning and resource cleanup.

Read the primary reference: React: synchronizing with Effects.

Reaching the recap and completing the quizzes are separate milestones.

    Next lesson: Effect Dependencies: Stay Synchronized with Current Values →