React applications are built using components, and components often need to do more than simply display information.
A component may need to:
- Store state
- Respond to user interactions
- Perform side effects
- Access browser APIs
- Share values between components
- Optimize expensive work
- Manage references
- Connect to external systems
React Hooks provide functions that allow components to use these capabilities.
Hooks became a major part of modern React development because they make it possible to reuse stateful logic without relying on class components.
You have already used one of the most important Hooks:
useState
For example:
import { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
Count: {count}
</button>
);
}
useState is a Hook.
In this chapter, you will learn what Hooks are, why they exist, the rules you must follow when using them, the most important built-in Hooks, and how to create your own custom Hooks.
What Are Hooks?
Hooks are functions provided by React that let function components use React features.
Some common Hooks include:
useState
useEffect
useContext
useRef
useReducer
useMemo
useCallback
useId
There are also specialized Hooks such as:
useActionState
useFormStatus
useOptimistic
useTransition
useDeferredValue
useSyncExternalStore
Hooks generally start with the word:
use
For example:
useState()
useEffect()
useContext()
The use naming convention is important because it helps developers and development tools recognize Hooks.
A Simple Hook Example
import { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>{count}</p>
<button
onClick={() => setCount((value) => value + 1)}
>
Increase
</button>
</div>
);
}
Here:
useState(0)
creates state for the component.
The Hook returns:
const [count, setCount] = useState(0);
where:
countis the current statesetCountupdates the state
Hooks do not replace components.
Instead, they give components additional capabilities.
Why Were Hooks Introduced?
Before Hooks, React commonly used class components when a component needed state or lifecycle-related behavior.
For example, older React code might look like:
class Counter extends React.Component {
state = {
count: 0
};
render() {
return (
<button>
{this.state.count}
</button>
);
}
}
Modern React generally uses function components with Hooks:
function Counter() {
const [count, setCount] = useState(0);
return (
<button>
{count}
</button>
);
}
Function components with Hooks are usually simpler to write and make it easier to reuse logic through custom Hooks.
Class components are still part of React and can appear in existing codebases, but new React code commonly uses function components and Hooks.
Why Hooks?
Hooks solve several practical problems in React development.
Hooks Allow State in Function Components
Before Hooks, function components were primarily used for presenting UI.
With Hooks, a function component can manage state:
function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
{count}
</button>
);
}
This makes function components capable of managing interactive behavior.
Hooks Make Logic Reusable
Suppose multiple components need to detect whether the browser is online.
Instead of copying the same logic into every component, you can create a custom Hook:
function useOnlineStatus() {
// reusable logic
}
Then:
function Dashboard() {
const isOnline = useOnlineStatus();
return <p>{isOnline ? "Online" : "Offline"}</p>;
}
Another component can use the same Hook:
function Header() {
const isOnline = useOnlineStatus();
return <span>{isOnline ? "Online" : "Offline"}</span>;
}
The logic is shared without sharing the state itself.
Each component gets its own Hook state.
Hooks Keep Related Logic Together
Imagine a component that needs to:
- Track a value
- Listen for an event
- Clean up the event listener
With Hooks, related logic can be kept together using useEffect and other Hooks.
This can make complex components easier to understand.
Hooks Reduce the Need for Wrapper Components
Older React patterns sometimes used techniques such as:
- Higher-order components
- Render props
- Complex component wrappers
These patterns are still useful in some situations, but custom Hooks often provide a simpler way to reuse behavior.
For example:
const width = useWindowWidth();
can be easier to understand than wrapping a component with another component solely to provide window-size logic.
Hooks Are Functions, but They Are Special
A Hook looks like a JavaScript function:
useState(0);
But Hooks have special rules.
You cannot treat a Hook like an ordinary function and call it anywhere.
For example, this is not valid:
if (isLoggedIn) {
useState(0);
}
Hooks need to be called in a predictable order.
This requirement leads to the Rules of Hooks.
Rules of Hooks
React has important rules that you should follow whenever you use Hooks.
The two fundamental rules are:
- Only call Hooks at the top level.
- Only call Hooks from React functions.
These rules help React correctly associate Hook state with a component across renders.
Rule One: Only Call Hooks at the Top Level
Do not call Hooks inside:
- Conditions
- Loops
- Nested functions
- Event handlers
try/catchblocksifstatements
For example, avoid:
if (isLoggedIn) {
const [user, setUser] = useState(null);
}
Instead, call the Hook at the top level:
const [user, setUser] = useState(null);
if (!isLoggedIn) {
return <p>Please log in.</p>;
}
The Hook itself is always called in the same place.
Do Not Call Hooks Inside Loops
Avoid:
for (const item of items) {
useState(item);
}
Hooks should not be called from loops.
Instead, move the Hook into a component or custom Hook.
For example:
function Item({ item }) {
const [selected, setSelected] = useState(false);
return (
<button
onClick={() => setSelected((value) => !value)}
>
{item.name}
</button>
);
}
Then:
{items.map((item) => (
<Item key={item.id} item={item} />
))}
Each Item component can independently use its own Hook.
Do Not Call Hooks Inside Event Handlers
Avoid:
function handleClick() {
const [count, setCount] = useState(0);
}
Hooks should not be created in response to an event.
Instead:
function Counter() {
const [count, setCount] = useState(0);
function handleClick() {
setCount((value) => value + 1);
}
return (
<button onClick={handleClick}>
{count}
</button>
);
}
The Hook is declared at the top level.
The event handler uses the state and setter.
Do Not Call Hooks Inside Nested Functions
Avoid:
function Component() {
function createState() {
const [value, setValue] = useState(0);
}
}
Instead:
function Component() {
const [value, setValue] = useState(0);
function createState() {
setValue(1);
}
}
The Hook stays at the component’s top level.
Rule Two: Only Call Hooks from React Functions
Hooks should be called from:
- React function components
- Custom Hooks
For example:
function Profile() {
const [name, setName] = useState("Alex");
return <h2>{name}</h2>;
}
This is a React function component.
A custom Hook can also call Hooks:
function useCounter() {
const [count, setCount] = useState(0);
return [count, setCount];
}
But an ordinary utility function should not call Hooks.
Avoid:
function calculateValue() {
const [value, setValue] = useState(0);
}
If the function needs to use a Hook, it should generally be a React component or a properly named custom Hook.
Why Do the Rules Exist?
React needs to know which Hook state belongs to which component and in what order.
Consider:
const [name, setName] = useState("");
const [age, setAge] = useState(0);
const [isAdmin, setIsAdmin] = useState(false);
React needs these Hooks to appear in the same order on every render.
If you conditionally skipped one:
if (isLoggedIn) {
useState("");
}
the order could change between renders.
That would make it difficult for React to correctly associate state with each Hook call.
The Rules of Hooks prevent this problem.
Image Placement: Rules of Hooks
Place this image immediately after the Rules of Hooks section.
Create a modern 16:9 educational infographic titled “Rules of Hooks”. Show a clean React component in the center with Hooks called at the top level. On one side, show correct patterns with check indicators: “Top Level”, “Function Component”, and “Custom Hook”. On the other side, show incorrect patterns such as “Inside if”, “Inside loop”, and “Inside event handler”. Use a polished Web4Learners developer aesthetic, rounded cards, subtle gradients, clean typography, minimal text, and a modern contemporary interface. Do not use red as the dominant design color.
Built-in Hooks
React provides many built-in Hooks for different types of functionality.
You do not need to memorize all of them immediately.
Instead, understand what each category is designed to do.
State Hooks
State Hooks allow components to store and update information.
The most common state Hooks are:
useState
useReducer
useState
useState is used for simple component state.
const [count, setCount] = useState(0);
It works well for values such as:
- Text
- Numbers
- Booleans
- Objects
- Arrays
For example:
const [name, setName] = useState("");
const [age, setAge] = useState(25);
const [isOpen, setIsOpen] = useState(false);
useReducer
useReducer is useful when state transitions are more complex or several updates are related.
const [state, dispatch] = useReducer(
reducer,
initialState
);
For example:
function reducer(state, action) {
switch (action.type) {
case "increment":
return {
...state,
count: state.count + 1
};
case "decrement":
return {
...state,
count: state.count - 1
};
default:
return state;
}
}
Then:
dispatch({ type: "increment" });
You will learn useReducer in detail later.
Context Hook
useContext allows a component to read a value from React Context.
For example:
const theme = useContext(ThemeContext);
Context can be useful for information that many components need, such as:
- Theme
- Current user
- Language
- Application-level configuration
Context does not automatically mean the data is global state in the same sense as an external state-management library. It is a mechanism for providing values through the component tree.
Effect Hook
useEffect allows a component to synchronize with systems outside React.
For example:
useEffect(() => {
document.title = "Web4Learners";
}, []);
Common uses include:
- Subscribing to external systems
- Connecting to browser APIs
- Synchronizing with non-React systems
- Performing certain network-related synchronization tasks
Effects should not be treated as the default solution for calculating values that can be calculated during rendering.
For example, avoid using an Effect simply to calculate:
const fullName = `${firstName} ${lastName}`;
That can be calculated directly during rendering.
Ref Hook
useRef lets you hold a value that persists between renders without causing a re-render when the value changes.
It is also commonly used to access a DOM element.
const inputRef = useRef(null);
Then:
<input ref={inputRef} />
You can use:
inputRef.current.focus();
to focus the input.
Refs are useful for values or objects that need to persist but are not themselves used to trigger rendering.
Performance Hooks
React provides Hooks that can help manage rendering performance and responsiveness.
Important examples include:
useMemo
useCallback
useTransition
useDeferredValue
useMemo
useMemo can cache the result of a calculation:
const filteredItems = useMemo(
() => filterItems(items, query),
[items, query]
);
It should be used when memoization provides a meaningful benefit, not automatically for every calculation.
useCallback
useCallback can cache a function reference:
const handleClick = useCallback(() => {
// ...
}, []);
This can be useful when function identity matters, such as when passing callbacks to memoized components.
useTransition
useTransition lets you mark certain state updates as non-urgent transitions.
const [
isPending,
startTransition
] = useTransition();
For example:
startTransition(() => {
setSearchResults(results);
});
This can help keep urgent interactions responsive while React works on less urgent updates.
useDeferredValue
useDeferredValue allows a value to lag behind the latest value so that less urgent UI can be updated later.
const deferredQuery = useDeferredValue(query);
This can be useful for interfaces where an expensive part of the UI should not block more urgent interactions.
Identifier Hook
useId generates unique IDs that can be useful for associating form controls with labels and other accessible elements.
const id = useId();
For example:
function EmailField() {
const id = useId();
return (
<>
<label htmlFor={id}>
Email
</label>
<input
id={id}
type="email"
/>
</>
);
}
useId is particularly useful when a reusable component needs unique IDs without manually creating them.
It should not be used as a list key.
Form and Action Hooks
Modern React also provides Hooks related to Actions and forms.
Examples include:
useActionState
useFormStatus
useOptimistic
You learned about these in the previous chapter.
For example:
const [
state,
formAction,
isPending
] = useActionState(
action,
initialState
);
And:
const { pending } = useFormStatus();
These Hooks are especially useful when working with modern form submission patterns.
Built-in Hooks Overview
Here is a useful high-level map:
| Hook | Main Purpose |
|---|---|
useState | Manage simple component state |
useReducer | Manage complex state transitions |
useContext | Read Context values |
useEffect | Synchronize with external systems |
useRef | Persist values or access DOM elements |
useMemo | Cache a calculation |
useCallback | Cache a function reference |
useTransition | Mark updates as non-urgent |
useDeferredValue | Defer less urgent UI updates |
useId | Generate unique IDs |
useActionState | Manage the result of an Action |
useFormStatus | Read a parent form’s status |
useOptimistic | Build optimistic UI updates |
You do not need to use every Hook in every application.
The important skill is knowing which Hook solves which type of problem.
Custom Hooks
A custom Hook is a JavaScript function that uses one or more React Hooks to encapsulate reusable logic.
Custom Hooks normally start with:
use
For example:
function useOnlineStatus() {
// Hook logic
}
The naming convention is important because it tells React developers and linting tools that the function follows Hook rules.
Why Create Custom Hooks?
Imagine you have two components that both need to track the browser’s online status.
Without a custom Hook, you might duplicate the logic.
With a custom Hook:
function useOnlineStatus() {
// shared logic
}
Both components can reuse it.
function Header() {
const isOnline = useOnlineStatus();
return (
<span>
{isOnline ? "Online" : "Offline"}
</span>
);
}
Another component:
function Footer() {
const isOnline = useOnlineStatus();
return (
<p>
Status: {isOnline ? "Online" : "Offline"}
</p>
);
}
The logic is shared.
Custom Hooks Share Logic, Not State
This is an important concept.
Suppose:
function useCounter() {
const [count, setCount] = useState(0);
return {
count,
increment: () =>
setCount((value) => value + 1)
};
}
If two components use it:
function ComponentA() {
const counter = useCounter();
}
and:
function ComponentB() {
const counter = useCounter();
}
they do not automatically share the same count.
Each component gets its own Hook state.
The custom Hook shares the logic for managing the state, not the state itself.
Creating a Custom Hook
Let’s build a simple useCounter Hook.
import { useState } from "react";
function useCounter(initialValue = 0) {
const [count, setCount] = useState(initialValue);
function increment() {
setCount((value) => value + 1);
}
function decrement() {
setCount((value) => value - 1);
}
function reset() {
setCount(initialValue);
}
return {
count,
increment,
decrement,
reset
};
}
Now a component can use it:
function Counter() {
const {
count,
increment,
decrement,
reset
} = useCounter(10);
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>
+
</button>
<button onClick={decrement}>
-
</button>
<button onClick={reset}>
Reset
</button>
</div>
);
}
The component becomes easier to read because the counter logic has been separated from the UI.
Custom Hook for Form State
Custom Hooks are particularly useful for reusable form logic.
For example:
import { useState } from "react";
function useInput(initialValue = "") {
const [value, setValue] = useState(initialValue);
function handleChange(event) {
setValue(event.target.value);
}
function reset() {
setValue(initialValue);
}
return {
value,
onChange: handleChange,
reset
};
}
Now:
function LoginForm() {
const email = useInput("");
const password = useInput("");
return (
<form>
<input
type="email"
value={email.value}
onChange={email.onChange}
/>
<input
type="password"
value={password.value}
onChange={password.onChange}
/>
</form>
);
}
The Hook handles the repeated input logic.
Custom Hook with useEffect
Custom Hooks can combine multiple Hooks.
For example, an online-status Hook could use useState and useEffect:
import {
useEffect,
useState
} from "react";
function useOnlineStatus() {
const [isOnline, setIsOnline] =
useState(navigator.onLine);
useEffect(() => {
function handleOnline() {
setIsOnline(true);
}
function handleOffline() {
setIsOnline(false);
}
window.addEventListener(
"online",
handleOnline
);
window.addEventListener(
"offline",
handleOffline
);
return () => {
window.removeEventListener(
"online",
handleOnline
);
window.removeEventListener(
"offline",
handleOffline
);
};
}, []);
return isOnline;
}
A component can now simply write:
function Status() {
const isOnline = useOnlineStatus();
return (
<p>
{isOnline
? "You are online"
: "You are offline"}
</p>
);
}
The component does not need to know how the browser events are managed.
Custom Hooks Can Accept Arguments
A custom Hook can receive parameters.
For example:
function useCounter(initialValue = 0) {
const [count, setCount] =
useState(initialValue);
return {
count,
increment: () =>
setCount((value) => value + 1)
};
}
Then:
const counter = useCounter(100);
Another component could use:
const counter = useCounter(0);
This makes custom Hooks flexible and reusable.
Custom Hooks Can Return Different Shapes
A custom Hook can return:
A Single Value
function useOnlineStatus() {
return true;
}
Then:
const isOnline = useOnlineStatus();
An Array
return [count, increment];
Then:
const [count, increment] =
useCounter();
An Object
return {
count,
increment,
reset
};
Then:
const {
count,
increment,
reset
} = useCounter();
Returning an object is often convenient when the Hook exposes several named values and functions.
Custom Hooks and the Rules of Hooks
Custom Hooks must follow the same Rules of Hooks.
This is valid:
function useCounter() {
const [count, setCount] = useState(0);
return count;
}
This is not valid:
function useCounter(enabled) {
if (enabled) {
const [count, setCount] =
useState(0);
}
}
Instead:
function useCounter(enabled) {
const [count, setCount] =
useState(0);
if (!enabled) {
return null;
}
return count;
}
The Hook itself is always called at the top level.
Custom Hooks Should Represent Behavior
A good custom Hook usually represents a meaningful piece of behavior.
Good examples:
useOnlineStatus
useWindowSize
useLocalStorage
useDebounce
useForm
usePagination
useSearch
useFetch
The exact implementation depends on the application’s requirements.
The goal is to extract reusable logic, not simply move random code into another file.
When Should You Create a Custom Hook?
Create a custom Hook when:
- Multiple components use similar stateful logic
- A component has a reusable behavior
- A combination of Hooks appears repeatedly
- You want to separate complex logic from UI
- You want a component to focus on rendering
For example, if three components all contain nearly identical logic for tracking online status, a custom Hook may be appropriate.
However, do not create a custom Hook just to wrap a single simple Hook without providing meaningful abstraction.
For example, this may add unnecessary complexity:
function useName() {
return useState("");
}
if there is no useful reusable behavior around it.
Hooks vs Utility Functions
Hooks and utility functions serve different purposes.
A utility function might be:
function formatPrice(price) {
return `$${price.toFixed(2)}`;
}
It does not use React Hooks.
A custom Hook might be:
function useOnlineStatus() {
const [isOnline, setIsOnline] =
useState(navigator.onLine);
// React-specific logic
return isOnline;
}
A useful rule is:
If the function uses Hooks, it should follow the Rules of Hooks and be designed as a custom Hook.
If it is just a pure calculation, a normal JavaScript function is often better.
Hooks and Component Design
Hooks encourage you to separate:
UI
+
Behavior
For example:
function SearchPage() {
const {
query,
results,
handleChange
} = useSearch();
return (
<SearchUI
query={query}
results={results}
onChange={handleChange}
/>
);
}
The component focuses primarily on describing the UI.
The custom Hook handles the behavior.
This can become especially useful as applications grow.
Image Placement: Custom Hooks
Place this image immediately after the Custom Hooks section.
Create a modern 16:9 educational infographic titled “Custom Hooks in React”. Show two different React components on the left and right both connecting to a central custom Hook named useOnlineStatus. Show the custom Hook containing reusable logic and each component receiving the resulting value independently. Include a subtle visual distinction between “Shared Logic” and “Separate State”. Use a modern Web4Learners developer aesthetic with rounded cards, subtle gradients, clean typography, minimal text, and polished contemporary UI.
Common Hooks Mistakes
Calling Hooks Conditionally
Avoid:
if (condition) {
useEffect(() => {
// ...
});
}
Instead, call the Hook and put the condition inside the Hook’s logic when appropriate.
Calling Hooks in Loops
Avoid:
items.forEach(() => {
useState(0);
});
Move the Hook into a component or custom Hook.
Calling Hooks in Event Handlers
Avoid:
function handleClick() {
useState(0);
}
Hooks belong at the top level of a component or custom Hook.
Using Hooks in Ordinary Utility Functions
Do not make an ordinary helper function call React Hooks.
If the function needs Hooks, make it a custom Hook and follow the Rules of Hooks.
Creating Too Many Custom Hooks
Custom Hooks are useful, but abstraction should have a purpose.
Do not create a custom Hook for every two lines of code.
Assuming Custom Hooks Share State
Two components using:
useCounter()
do not automatically share the same counter state.
Each Hook call has its own state.
Using useMemo and useCallback Everywhere
These Hooks are optimization tools.
They should not be added automatically to every calculation or function.
First make the application correct and clear. Use memoization when it provides a meaningful performance benefit or when a stable reference is actually needed.
Using Effects for Derived Data
Avoid using an Effect just to calculate something from existing state:
useEffect(() => {
setFullName(`${firstName} ${lastName}`);
}, [firstName, lastName]);
Instead:
const fullName = `${firstName} ${lastName}`;
This keeps the data flow simpler.
Best Practices for Hooks
Follow the Rules of Hooks
Always call Hooks at the top level of React components or custom Hooks.
Keep Components Understandable
If a component becomes difficult to follow because it contains a large amount of reusable logic, consider extracting that behavior into a custom Hook.
Choose Hooks Based on the Problem
Use:
useState
for straightforward state.
Use:
useReducer
when state transitions become more complex.
Use:
useContext
when a value needs to be consumed through Context.
Use:
useEffect
for synchronization with external systems.
Use:
useRef
for persistent values or DOM references that do not need to trigger rendering.
Use:
useMemo
useCallback
when memoization is useful.
Keep Custom Hooks Focused
A custom Hook should ideally represent a clear behavior.
For example:
useOnlineStatus()
is easier to understand than a custom Hook containing unrelated application logic.
Keep Rendering Logic Separate from Complex Behavior
When appropriate, move complex reusable behavior into a custom Hook while leaving the component responsible for rendering the UI.
Prefer Clear Code Over Premature Optimization
Hooks such as useMemo and useCallback are powerful, but adding them everywhere can make code harder to understand.
Use them when there is a clear reason.
Hooks Learning Roadmap
As you continue through React, you can learn Hooks in roughly this order:
useState
↓
useEffect
↓
useContext
↓
useRef
↓
useReducer
↓
Custom Hooks
↓
useMemo / useCallback
↓
useTransition / useDeferredValue
↓
Advanced Hooks
This is not a strict requirement. Different applications require different Hooks.
The important thing is to understand the problem each Hook solves.
Web4Learners Example
Imagine you are building the Web4Learners tutorial website.
You might have a tutorial search feature.
The component needs to:
- Store the search query
- Filter tutorials
- Track the selected category
- Manage search-related behavior
A custom Hook could encapsulate this behavior:
function useTutorialSearch(tutorials) {
const [query, setQuery] = useState("");
const filteredTutorials =
tutorials.filter((tutorial) =>
tutorial.title
.toLowerCase()
.includes(query.toLowerCase())
);
return {
query,
setQuery,
filteredTutorials
};
}
The component can then use:
function TutorialPage({ tutorials }) {
const {
query,
setQuery,
filteredTutorials
} = useTutorialSearch(tutorials);
return (
<>
<input
value={query}
onChange={(event) =>
setQuery(event.target.value)
}
placeholder="Search React tutorials"
/>
<TutorialList
tutorials={filteredTutorials}
/>
</>
);
}
The component is now primarily concerned with rendering.
The custom Hook contains the reusable search behavior.
If another page needs the same search behavior, it can use the same Hook.
Practice Exercise
Create a custom Hook called:
useCounter
It should support:
Increment
Decrement
Reset
It should accept an initial value:
useCounter(10)
and return:
{
count,
increment,
decrement,
reset
}
Then create two components:
CounterA
CounterB
Use the custom Hook in both components.
Experiment with changing the counter in CounterA.
Observe whether the state in CounterB changes.
It should not.
This demonstrates an important concept:
Custom Hooks share logic, not state.
As an additional exercise, create:
useInput
that manages an input’s value, change handler, and reset behavior.
Hooks Cheat Sheet
| Hook | What It Helps With |
|---|---|
useState | Component state |
useReducer | Complex state transitions |
useContext | Reading Context |
useEffect | External system synchronization |
useRef | Persistent values and DOM references |
useMemo | Memoizing calculations |
useCallback | Memoizing function references |
useTransition | Non-urgent updates |
useDeferredValue | Deferring less urgent values |
useId | Unique IDs |
useActionState | Action results and state |
useFormStatus | Form submission status |
useOptimistic | Optimistic UI |
| Custom Hook | Reusable stateful logic |
Rules of Hooks Cheat Sheet
Remember these core rules:
Call Hooks at the top level.
↓
Do not call them inside conditions.
↓
Do not call them inside loops.
↓
Do not call them inside event handlers.
↓
Call them from React components or custom Hooks.
Key Takeaways
- Hooks are React functions that allow function components to use React features.
useStateis one of the most commonly used Hooks.- Hooks are a fundamental part of modern React development.
- Hooks make stateful and reusable logic easier to organize.
- Function components can use state and other React capabilities through Hooks.
- Hooks must follow the Rules of Hooks.
- Hooks should be called at the top level, not inside conditions, loops, event handlers, or nested functions.
- Hooks should be called from React function components or custom Hooks.
- React provides many built-in Hooks for state, effects, context, refs, performance, forms, and other use cases.
useStatemanages straightforward component state.useReduceris useful for more complex state transitions.useContextreads values provided through React Context.useEffectis used to synchronize with external systems.useRefstores persistent values or provides access to DOM elements without using state for that purpose.useMemoanduseCallbackprovide memoization when it is useful.useTransitionanduseDeferredValuehelp manage less urgent rendering work.useIdcan generate unique IDs for accessible relationships.- Modern React also includes Hooks for Actions, forms, and optimistic UI.
- Custom Hooks allow you to extract and reuse stateful logic.
- Custom Hooks should normally start with
use. - Custom Hooks share logic, not state.
- Each component calling the same custom Hook receives its own Hook state.
- A custom Hook should represent a meaningful reusable behavior.
- Hooks are not a replacement for good component design. They are tools that help you organize state and behavior effectively.