Building Custom React HooksEntry 4 of 5
Each Call Gets Its Own State
Every component that calls a custom hook gets a separate, independent copy of the hook's state and effects.
Notes
- Custom hooks share logic, not data. Calling
useFetchin two components runs two requests and keeps two separate sets ofisFetching,error, andfetchedData. - Think of a custom hook as a factory: each call creates new state, just like calling
useStatetwice. - To share the same state between components, combine the hook with Context (see Context API & useReducer, Entry 4) or use a store such as Redux Toolkit.
What / Why / When
- What
Per-component state isolation.
- Why
Components stay independent and predictable; one component's data can't change another's.
- When to share instead
Several components must see the same data at the same time (a cart, the logged-in user).
Code compare
function PlayersSummary() { const { fetchedData } = useFetch(fetchPlayers, []); // request #1, own state return <p>{fetchedData.length} players</p>;}function PlayersTable() { const { fetchedData } = useFetch(fetchPlayers, []); // request #2, separate state return <table>{/* ... */}</table>;}Where state lives depends on the tool, which maps neatly onto React's options:
// Per component (like a custom hook): each call creates new signalsprotected players = injectFetch(() => firstValueFrom(this.playersService.fetchPlayers()), []);// Shared app-wide (like Context or a global store): one instance for everyone@Injectable({ providedIn: 'root' })export class PlayersStore {}// Shared within a subtree (like a Context provider around one section)@Component({ selector: 'app-team', providers: [PlayersStore], template: `...` })export class TeamComponent {}Differences and gotchas
- A common mistake coming from Angular: assuming a custom hook behaves like a
providedIn: 'root'service. It doesn't; it behaves like a function called per component.
Quick reference
| Scope | React | Angular |
|---|---|---|
| Per component | Custom hook | Function with signals / component-level providers |
| Shared in a subtree | Context provider around the subtree | Service in a component's providers |
| Shared app-wide | Context at the root / Redux Toolkit | providedIn: 'root' service |