useInterval with useEffectEvent
The tick reads the latest left without left being a dependency, so the interval starts once and stops when the delay becomes null. Change the delay to 1000 and click Faster mid-way: the interval keeps running and the new step is used at once.
Seven small hooks cover jobs almost every app has: useToggle, useLocalStorage, useDebounce, useOnlineStatus, useMediaQuery, usePrevious and useInterval; building them yourself teaches the patterns behind every hook library.
Change the code and press Run (Ctrl+Enter). Predict what will happen first, then break it on purpose and read what changes. Your edits are saved and match the lesson page.
Ready for more? This phase has 6 hands-on exercises with automatic checks.
Practice questions
Write the code in the editor, run it, then open the model answer to compare.
Write useCounter as a recipe: useCounter({ min = 0, max = 10 } = {}) returns { count, inc, dec } and never leaves the range.
Write useWindowWidth() that returns window.innerWidth and updates on resize, with cleanup.
Use useDebounce and useLocalStorage together: a notes textarea that saves its text 500 ms after the user stops typing.
Explain it without notes
How does useDebounce make sure only the last value is used?
Why does useLocalStorage read storage in a lazy initialiser and write in an effect?
Why is a naive useInterval either stale or constantly restarting, and how does useEffectEvent fix it?
What is the difference between the ref-based and the state-based usePrevious?
Preview
Console
Nothing logged yet.Expected console output
interval started: 100 ms
tick: 3
tick: 2
tick: 1
tick: 0