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.
Understand
Separate rendering, events and synchronization.
Build
Keep a browser title aligned with the selected class.
Check
Identify calculations that do not require an Effect.
Commit first, synchronize afterward
State
The selected class is 7A.
Render and commit
React describes and updates the class screen.
Synchronize
The Effect sets the browser tab title.
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.
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.