REACT FUNDAMENTALS · BYTE 01
Component tree
One App component describes the first task list.Why tasks disappear after refresh
Our To-Do List now works until the browser refreshes. React component state is memory, not permanent storage. We can keep a small personal demo list in localStorage, a browser feature, and use useEffect to synchronize changes.
What you will build: Milestone 4 of a small browser-based To-Do List. No backend or advanced architecture is needed.
Saving tasks in the browser
The task list on screen is like a whiteboard. localStorage is a notebook where we keep a copy. When the page opens, we read the notebook. Whenever the list changes, we update the notebook.
Effects and browser synchronization
An Effect runs after React has committed the UI and can synchronize with something outside React. useEffect(() => { localStorage.setItem(...) }, [tasks]) says: after tasks changes, save a JSON representation. A lazy useState(() => ...) initializer reads saved tasks only at initial mounting in this client-only Vite example. JSON.stringify converts the array to text; JSON.parse reads it back. The [tasks] dependency tells React which reactive value the Effect uses. Not all Effects need cleanup: saving one value doesn't create a subscription. Timers and event listeners do need cleanup.
Trace save and restore
Before the diagram: React state holds the current list while the page is open. Browser localStorage holds serialized text between refreshes on the same browser. An Effect synchronizes React state with that external storage.
CONCEPT → CODE → OUTPUT · BYTE 02
From data to a reusable TaskItem
Select any stage to inspect what React or JavaScript does.
Stores task objects with an id and title
Predict the output: After adding a task, the save Effect stores JSON. On a subsequent refresh, the state initializer loads the JSON before the initial list is displayed. Browser storage is not a database or multi-device synchronization.
-
App mounts → lazy state initializer reads saved JSON or defaults.
-
React renders the current tasks.
-
Learner adds or completes a task.
-
React commits the changed list.
-
Effect writes the new list to localStorage.
-
Refresh creates a new app instance → initial state reads the saved list.
Explore the Effect lifecycle
REACT VISUAL LAB · BYTE 01
Component tree
One App component describes the first task list.
My Task Manager
Learn React one small step at a time.
- Read React notes
- Practise JSX
This is a concept simulator. Build the actual React code in the walkthrough below.
Check the idea: Answer this question before coding.
INTERACTIVE REACT LAB · BYTE 01
Which React component describes the Task Manager screen?
Persist tasks using localStorage
Our learning project: A tiny Task Manager, not an enterprise support system. The app grows gradually across the five Bytes; each code step below tells you exactly which file to edit.
Milestone 4: React useEffect: Keep Tasks After a Page Refresh.
Step 1: Keep your working component and state
Where: src/App.tsx
01// Keep TaskItem, addTask, toggleTask and the JSX from Byte 03.02// Only change how tasks state is initialized and saved.
Expected screen/result: The Add and Complete behavior remains unchanged.
Step 2: Read saved tasks when initializing state
Where: src/App.tsx
01// Replace the initial useState<Task[]>(initialTasks) declaration:02const [tasks, setTasks] = useState<Task[]>(() => {03try {04const saved = window.localStorage.getItem('my-tasks');05return saved ? JSON.parse(saved) as Task[] : initialTasks;06} catch {07return initialTasks;08}09});
Expected screen/result: Saved tasks load on a browser-only Vite app. This initial code intentionally targets client-only rendering.
Step 3: Add a save Effect
Where: src/App.tsx
01// Import useEffect alongside useState:02import { useEffect, useState } from 'react';0304// Inside App, below tasks state:05useEffect(() => {06window.localStorage.setItem('my-tasks', JSON.stringify(tasks));07}, [tasks]);
Expected screen/result: Adding or completing a task now updates browser storage after render.
Step 4: Verify the save-and-restore flow
Where: Browser steps
011. Add a new task.022. Mark it completed.033. Refresh the browser tab.044. Check that both the task and checkbox state remain.
Expected screen/result: Task data survives refresh on that browser, but is not shared between devices.
Project checkpoint: Tasks survive refresh.
Common useEffect mistakes
- Calling
JSON.parsewithout handling failures: Damaged text can crash initialization; usetry/catch. - Effect with no dependency array: It runs after every committed render; define the relevant dependencies.
- Saving a derived count separately: Compute pending tasks during render instead.
- Mistaking browser storage for a database: It is local to that browser and is not suitable for shared accounts or confidential data.
- Confusing cleanup: A one-off storage write needs no cleanup; interval/listener subscriptions do.
Where synchronization matters
React uses the same underlying idea in many applications: a product list, a shopping basket, a learning progress page, or a dashboard. We are using task management only to keep the learning journey simple.
What happens during a page refresh
| What a learner sees | What React or the browser does |
|---|---|
| refresh restores tasks | Initial state reads localStorage → render tasks → task changes → render commits → Effect writes localStorage |
| A task list ready for interaction | React creates output from component inputs and state |
Clear saved tasks and restore defaults
Challenge 1: Add Buy notebook, complete it, and refresh. Both the item and its completed checkbox should persist.
Challenge 2: Open DevTools → Application → Local Storage and locate my-tasks.
Challenge 3: Delete that key and refresh. Explain why the starter tasks return.
Interview Bit
Question: What is useEffect, and why do we use it in our To-Do List?
Simple answer: useEffect synchronizes a component with something outside React. In our browser-only To-Do List, it writes changed tasks to localStorage so they can be restored after a refresh.
How to explain it: Point to the related code in the To-Do List and describe what appears in the browser.
Key Takeaways
- Component state alone does not survive page refresh.
- localStorage keeps data in one browser.
- JSON.stringify converts task data to text.
- JSON.parse restores saved data.
- A lazy state initializer reads saved tasks when mounting.
- useEffect can synchronize React state with localStorage.
- Dependencies identify reactive values used by an Effect.
- Browser storage is not a shared secure backend.
Knowledge Check
Review these common questions before attempting the scored quiz.
- Why useEffect for saving? Storage is an external system.
- Why no Effect for pending count? It is derived from existing state.
- Does localStorage sync across browsers? No.
PRACTISE AND CHECK
Knowledge Check · 5 questions
Choose one answer for every question. Submit to see your score and explanations.
0 of 5 answered