Lesson 5 of 80
A custom hook is just a function that calls other hooks — composition, not a new mechanism, with one hard rule underneath it.
12 min read
Every option explains itself — why the right one is right, and why each wrong one is wrong. Miss one and it comes back later on a spaced-repetition schedule.
Question 1 of 4
Two different components both call the same custom hook, useToggle(). Do they end up sharing state?
Hints without spoilers, and a plain explanation of why a wrong answer was wrong — answered only from this lesson. Free account, no card.
Sign up freeWhat interviewers actually ask about this, and what a strong answer has to cover.
A strong answer covers
Likely follow-ups
A custom hook is nothing more than a JavaScript function that calls useState, useEffect, or other hooks inside it. Naming it useSomething is a convention, not magic — it's the same useState you already know, just wrapped in a function you can reuse.
function useToggle(initial = false) {
const [value, setValue] = useState(initial);
const toggle = () => setValue((v) => !v);
return [value, toggle];
}
function Sidebar() {
const [open, toggleOpen] = useToggle(false);
return <button onClick={toggleOpen}>{open ? "Close" : "Open"}</button>;
}
useToggle isn't a new React feature — it's a plain function that happens to call useState. Every component that calls it gets its own independent open/toggleOpen pair; the hook doesn't share state between callers, no matter how many components use it.
function Broken({ isLoggedIn }) {
if (isLoggedIn) {
const [name, setName] = useState(""); // ❌ conditional hook call
}
const [age, setAge] = useState(0);
// ...
}
React doesn't track hook state by variable name — it tracks it by the order hooks are called in, per component instance, like slots in a list: 1st hook call, 2nd hook call, 3rd… If isLoggedIn is true on one render and false on the next, the useState calls shift position, and React attaches the wrong stored value to the wrong slot. That's the entire reason for the rule: call hooks unconditionally, at the top level, in the same order every render.
Two components both need mouse-position tracking — the same useState + useEffect, duplicated.
useToggle() each get their own useState underneath — completely independent.use prefix is a convention, not a language feature. Nothing in JavaScript enforces it; it exists so linters (and other developers) can recognize a function needs to follow the rules of hooks.useDebouncedValue might internally use useState and useEffect; something else can build on top of useDebouncedValue.useState/useEffect calls happen either way; you're only giving a reusable name to a pattern you'd otherwise repeat."What would break if you called useState inside an if?" tests whether you understand hooks aren't magic annotations — they're ordinary function calls React tracks positionally, which is a very different mental model from most APIs, and one that has real, mechanical consequences.