Use React Hooks to manage state and side effects in function components—with patterns you can take straight into a small app.
What you will learn
useStatefor local UI stateuseEffectfor synchronization with external systemsuseContextfor shared values without prop drilling- Rules of Hooks and when not to invent custom state machines yet
Prerequisites
- JavaScript fundamentals
- A React 18+ sandbox or Vite React app (React docs — Quick Start)
Why Hooks
Hooks let function components hold state and run effects without classes. Prefer them for new UI code; keep effects focused on synchronization, not business-logic sprawl.
useState
import { useState } from "react";
export function Counter() {
const [count, setCount] = useState(0);
return (
<button type="button" onClick={() => setCount((value) => value + 1)}>
Clicked {count}
</button>
);
}Docs: useState.
useEffect
import { useEffect, useState } from "react";
export function WindowWidth() {
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
const onResize = () => setWidth(window.innerWidth);
window.addEventListener("resize", onResize);
return () => window.removeEventListener("resize", onResize);
}, []);
return <p>Width: {width}px</p>;
}Docs: useEffect and Synchronizing with Effects.
useContext
import { createContext, useContext, useState } from "react";
const ThemeContext = createContext("light");
export function App() {
const [theme, setTheme] = useState("light");
return (
<ThemeContext.Provider value={theme}>
<button type="button" onClick={() => setTheme((t) => (t === "light" ? "dark" : "light"))}>
Toggle
</button>
<Panel />
</ThemeContext.Provider>
);
}
function Panel() {
const theme = useContext(ThemeContext);
return <p>Theme: {theme}</p>;
}Rules of Hooks
- Call Hooks only at the top level of React functions
- Call Hooks only from React components or custom Hooks
- Keep dependency arrays honest—do not silence the linter without understanding the bug you hide
Custom Hook sketch
function useOnlineStatus() {
const [online, setOnline] = useState(navigator.onLine);
useEffect(() => {
const on = () => setOnline(true);
const off = () => setOnline(false);
window.addEventListener("online", on);
window.addEventListener("offline", off);
return () => {
window.removeEventListener("online", on);
window.removeEventListener("offline", off);
};
}, []);
return online;
}Extract a Hook when two components share the same stateful logic—not when you only want a shorter file.
Practice checklist
- Build a counter with functional updates (
setCount(c => c + 1)) - Add an effect with a cleanup function and prove cleanup runs (log on unmount)
- Share a theme through context across two child components
Common pitfalls
- Fetching in
useEffectwithout cleanup/abort - Storing derived values in state instead of computing them
- Overusing context for high-frequency updates
Sources and further reading
Who this guide is for
- React developers moving from class components
- Frontend engineers debugging state and effect behavior
- Reviewers who want maintainable component boundaries
Definition of done
A small component flow where state has one owner, effects synchronize only with external systems, cleanup is verified, and shared logic is extracted only when reuse is real.
Finishing the commands is not the same as finishing the guide. Keep the result only when another person can reproduce it, inspect the evidence, and understand the remaining risks.
Professional workflow
Phase 1 — Design state ownership
Goal: Keep the smallest possible source of truth.
- List user-controlled state separately from values that can be derived.
- Place each state value at the nearest common owner.
- Define events in user language before writing setters.
Verification: Removing any state variable would lose real information rather than a cached calculation.
Phase 2 — Add external synchronization
Goal: Use effects only where React must coordinate with something outside rendering.
- Name the external system: browser API, network, timer, or subscription.
- Implement cleanup before adding more branches.
- Test remounting and rapid dependency changes.
Verification: Development Strict Mode does not leave duplicate listeners, requests, or timers.
Phase 3 — Extract and test
Goal: Create a reusable Hook with a narrow contract.
- Extract only logic used by more than one component or complex enough to test independently.
- Return data and actions rather than markup.
- Test visible behavior and cleanup, not private implementation details.
Verification: A second component can use the Hook without knowing its internal state structure.
Review questions before you continue
- Is this value state, a prop, or a derivation?
- Which external system requires this effect?
- What must happen when dependencies change or the component unmounts?
- Would a reducer make a multi-event transition easier to review?
If an answer is unknown, record it as an explicit follow-up instead of hiding the uncertainty behind a successful demo.
Troubleshooting decision guide
- An effect loops: find the changing dependency instead of suppressing the lint rule.
- State appears stale: use functional updates when the next value depends on the previous one.
- Two values drift apart: store one source and derive the other during render.
- Context causes broad rerenders: split stable data from frequently changing values.
Change one variable at a time, preserve the first useful error, and write down the command or condition that fixed it. That turns a private debugging session into team knowledge.
Production-readiness checklist
- Keep dependency linting enabled.
- Abort or ignore obsolete asynchronous work.
- Provide loading, empty, error, and success states.
- Measure before adding memoization.
- Test keyboard and screen-reader behavior for stateful controls.
These checks are intentionally stricter than a beginner demo. Use them to decide whether to continue learning, run a controlled pilot, or request specialist review.
Your next 30 minutes
- Refactor one effect that only derives state.
- Add a cleanup assertion to one component test.
- Document the ownership of each state variable.
- Continue with the official React guidance on effects and custom Hooks.
CTA: Pick the first unchecked step, complete it now, and save the evidence in your project README or decision log. Then open the official documentation linked below before adopting the result in production.