Knowing when to extract a component or custom hook is a judgment call, not a line-count rule. Extract to remove real duplication or coupling, and leave code alone when it is already clear.
Extract a component when the UI repeats
A component is the right extraction when the same markup appears in more than one place, or when a piece of the screen has its own state and changes independently. The extracted component receives what it needs as props and owns nothing else.
A product row that appears in a list and in a search result is one component. A header that changes on its own schedule is another.
The signal is not length; it is that the piece is a reusable or independent unit. If two copies share a border radius but nothing else, they are not the same component.
Extract a custom Hook when the logic repeats
A Hook is the right extraction when several components share stateful behavior, not shared markup. The classic case is open/close or on/off state used by a modal, a menu, and a dropdown.
import { useState } from "react";
export function useToggle(initial = false) {
const [on, setOn] = useState(initial);
function toggle() {
setOn((current) => !current);
}
return { on, toggle };
}The Hook earns its place when two or more components need the same toggle behavior. If only one component needs it, the state can stay inside that component. The full extraction process is in How to Create a Custom Hook in React, and reusing stateful logic without reusing state explains what a Hook does and does not share.
Leave it alone when the duplication is small
Not every repeated line is worth an abstraction. Two similar paragraphs that will likely diverge are fine as two paragraphs. Extracting them early locks them together and makes every future difference a negotiation.
The React docs say the same about Hooks: you do not need to extract one for every little duplicated bit of code. Some duplication is fine. A useful rule is to wait for the second use, and often the third, before generalizing.
Component or Hook?
Use this table when the two choices feel close.
| Extract a component when | Extract a Hook when |
|---|---|
| The markup repeats | The stateful logic repeats |
| The piece has its own state | Many components need the same behavior |
| The piece changes independently | The logic hides an external system |
A well-designed Hook also makes the calling component read like intent, so name it after what it does rather than how it works.
The test
Before extracting, ask one question: does the split make the data flow clearer, or does it add a layer of props that hides where data comes from? If the answer is clearer, extract. If it is just shorter lines and more files, leave it.
Rune AI
Key Insights
- Extract a component for repeated markup or independent UI.
- Extract a custom Hook for repeated stateful logic.
- Do not extract just because a file is long.
- Some duplication is cheaper than a bad abstraction.
- The boundary should make the data flow clearer.
Frequently Asked Questions
Is duplicated code always worth extracting?
Should I extract based on file length?
Conclusion
Extract a component for repeated markup or an independent piece of UI, and a custom Hook for repeated stateful logic. Leave code alone when the duplication is small or the abstraction would be premature.
More in this topic
How to Build a Dropdown Menu in React
Build a React dropdown menu with the ARIA menu button pattern. Handle open and close, keyboard arrows, and clicks outside the menu.
How to Animate React Components with Motion
Animate React components with the Motion library. Set up motion, add enter, hover, and exit animations, and respect reduced motion.
Headless UI Components Explained: Logic Without Locked Styling
Understand headless UI components and how libraries like Radix give you unstyled, accessible behavior that you style yourself.