Custom Hooks — Reusing Logic
BookCard has an open/closed state with open, close and toggle helpers. So does AuthorCard. So does the filters panel. The same five lines, pasted three times. Components let you reuse markup; custom hooks let you reuse the logic behind it.
The rule
A function named use-something that calls hooks: shared logic, separate state.
// useToggle.js
import { useState } from 'react';
export function useToggle(initial = false) {
const [isOpen, setIsOpen] = useState(initial);
const open = () => setIsOpen(true);
const close = () => setIsOpen(false);
const toggle = () => setIsOpen(o => !o);
return { isOpen, open, close, toggle };
}function BookCard({ book }) {
const { isOpen, toggle } = useToggle();
return (
<article>
<h2 onClick={toggle}>{book.title}</h2>
{isOpen && <p>{book.summary}</p>}
</article>
);
}Named use-something. The use prefix is a promise: "this function calls hooks, so the rules of hooks apply to it." The linter relies on the name to check it, and readers rely on it too. A helper that calls no hooks should not start with use.
Calls hooks. Inside, you can use any hook — useState, useEffect, useRef, even other custom hooks. It returns whatever is useful: a value, an object, an array.
Shared logic, separate state. This surprises many people. Each component that calls useToggle() gets its own isOpen. Opening one book card does not open the others. A custom hook shares how the state works, not the state itself. To truly share one value, lift it up or use context.
Older patterns. Before hooks, logic was shared in two other ways you will still meet in older code:
- A higher-order component is a function that takes a component and returns a new, wrapped one:
export default withToggle(BookCard). - A render prop is a prop holding a function that returns JSX:
<Toggle render={isOpen => ...} />.
Both still work, but they add wrapper components and nesting. A custom hook is just a function call at the top of a component, which is why modern code prefers it.
The shortcut
Spot the repeat, cut the hook lines out, and name what they do. Whatever the components need back becomes the return value.
Spot the repeat
BookCardandAuthorCardboth haveuseState(false)plus three helper functions.
Drills
Answer fast — trust the rule.
Which name is right for a function that calls useState and useEffect to track window width?
Two components each call useToggle(). One calls toggle(). What happens to the other?
What is withToggle(BookCard) an example of?
Where can a custom hook be called?
Remember
- A function named use-something that calls hooks: shared logic, separate state.
- Spot the repeat, cut the hook lines out, return what callers need.
- Trap: expecting two calls to share state; use lifting or context for that.
