Lesson 4 / 7

State and Hooks

Props flow in from a parent; state is data a component owns and manages itself, and — critically — updating it triggers React to automatically re-render that component with the new value.

useState

import { useState } from "react";nnfunction LessonCounter() {n    const [completed, setCompleted] = useState(0);nn    return (n        <div>n            <p>Completed: {completed}</p>n            <button onClick={() => setCompleted(completed + 1)}>n                Mark lesson donen            </button>n        </div>n    );n}

useState(0) declares a piece of state starting at 0, and returns a pair: the current value (completed) and a function to update it (setCompleted). Calling setCompleted is what actually triggers a re-render — directly reassigning completed would not.

The Rules of Hooks

useState is called a Hook — a special React function, always starting with use, that only works inside a component (or inside another Hook). Hooks must always be called in the exact same order on every render, which means they can never be placed inside an if statement or a loop — this is a strict rule, and React’s tooling will warn you loudly if you break it.

useEffect — running code in response to changes

import { useState, useEffect } from "react";nnfunction LessonTimer() {n    const [seconds, setSeconds] = useState(0);nn    useEffect(() => {n        const interval = setInterval(() => setSeconds(s => s + 1), 1000);n        return () => clearInterval(interval);   // cleanup, runs when the component unmountsn    }, []);   // empty array: run once, when the component first appearsnn    return <p>{seconds} seconds elapsed</p>;n}

useEffect runs side effects — things outside of just rendering markup, like timers, subscriptions, or fetching data (covered in the next lesson). The array at the end (the “dependency array”) controls when it re-runs; an empty array means “only once, when this component first appears.”