javascript 45 lines · 9 steps

A React hook that persists form state to localStorage

usePersistentForm keeps form values in localStorage with debounced writes so a refresh never loses what the user typed.

Explained by highlit
1import { useState, useEffect, useCallback, useRef } from "react";
2 
3export function usePersistentForm(storageKey, initialValues) {
4 const [values, setValues] = useState(() => {
5 try {
6 const stored = window.localStorage.getItem(storageKey);
7 return stored ? { ...initialValues, ...JSON.parse(stored) } : initialValues;
8 } catch {
9 return initialValues;
10 }
11 });
12 
13 const saveTimer = useRef(null);
14 
15 useEffect(() => {
16 clearTimeout(saveTimer.current);
17 saveTimer.current = setTimeout(() => {
18 try {
19 window.localStorage.setItem(storageKey, JSON.stringify(values));
20 } catch {
21 /* quota exceeded or storage unavailable */
22 }
23 }, 400);
24 return () => clearTimeout(saveTimer.current);
25 }, [storageKey, values]);
26 
27 const handleChange = useCallback((event) => {
28 const { name, type, value, checked } = event.target;
29 setValues((prev) => ({
30 ...prev,
31 [name]: type === "checkbox" ? checked : value,
32 }));
33 }, []);
34 
35 const setField = useCallback((name, value) => {
36 setValues((prev) => ({ ...prev, [name]: value }));
37 }, []);
38 
39 const reset = useCallback(() => {
40 window.localStorage.removeItem(storageKey);
41 setValues(initialValues);
42 }, [storageKey, initialValues]);
43 
44 return { values, handleChange, setField, reset };
45}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1A lazy initializer in useState lets you hydrate from storage exactly once without re-reading on every render.
  2. 2Debouncing writes through a ref'd timer avoids hammering localStorage on every keystroke.
  3. 3Wrapping storage access in try/catch keeps the hook resilient when storage is full or unavailable.

Related explainers

Share this explainer

Here's the card — post it anywhere.

A React hook that persists form state to localStorage — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code