Building Custom React HooksEntry 1 of 5
What a Custom Hook Is
A custom hook is a function whose name starts with use and that calls other hooks (useState, useEffect, etc.) to package reusable logic.
Notes
- A custom hook wraps logic that would otherwise be copied between components: data fetching, subscriptions, timers, form handling.
- The
useprefix is required. It tells React and theeslint-plugin-react-hookslinter to apply the Rules of Hooks to the function (see React Essentials, Entry 6). - Custom hooks follow the same rules as built-in hooks: call them only inside components or other hooks, and only at the top level.
- A custom hook shares logic, not state. Each component that calls it gets its own state (Entry 4).
- It can return anything: a value, an object, a tuple, or functions.
What / Why / When
- What
A reusable function built from other hooks.
- Why
Removes duplicated stateful logic and keeps components focused on rendering.
- When
The same combination of state and effects appears in more than one component.
- Use case
A
useFetchhook that handles loading, error, and data state for any request.
Code compare
import { useState } from "react";// ✅ A custom hook: starts with "use" and calls other hooksexport function useToggle(initialValue = false) { const [isOn, setIsOn] = useState(initialValue); function toggle() { setIsOn((prev) => !prev); } return [isOn, toggle] as const;}// Usagefunction Menu() { const [isOpen, toggleOpen] = useToggle(); return <button onClick={toggleOpen}>{isOpen ? "Close" : "Open"} menu</button>;}Angular has no hooks, so reusable logic takes one of two forms:
- A service when the logic or state should be shared (see Context API & useReducer, Entry 4).
- A plain function that creates signals and, when needed, calls
inject(). Functions that callinject()must run in an injection context (a field initializer or constructor), and by convention are often namedinjectX.
import { signal } from "@angular/core";export function createToggle(initialValue = false) { const isOn = signal(initialValue); return { isOn: isOn.asReadonly(), toggle: () => isOn.update((prev) => !prev), };}@Component({ selector: "app-menu", template: ` <button (click)="menu.toggle()">{{ menu.isOn() ? "Close" : "Open" }} menu</button> `,})export class MenuComponent { protected menu = createToggle();}Differences and gotchas
- React requires the
useprefix and the Rules of Hooks. Angular functions have no naming rule; only functions that callinject()oreffect()must run in an injection context. - Angular also reuses DOM behavior through directives (including
hostDirectives), which have no direct React equivalent.
Quick reference
| React | Angular |
|---|---|
function useX() { useState(...) } | Function creating signals / service |
use prefix required | No naming rule (injectX by convention) |
| Rules of Hooks | Injection context for inject()/effect() |