How to Update State with React Hooks
React Hooks allow you to manage and update state inside functional
components without writing class components. This article explains how
to update state values using the useState and
useReducer hooks, how to handle functional state updates,
and how to trigger side effects when hook values change.
Updating Basic State with useState
The useState hook is the primary tool for managing state
in React functional components. It returns an array with two elements:
the current state value and a setter function to update that value.
To update the state, you call the setter function with the new value:
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
Count: {count}
</button>
);
}Using Functional Updates
If your new state depends on the previous state, you should pass a function to the setter instead of a direct value. This prevents bugs related to asynchronous state batching.
// Safely updating state based on previous state
setCount(prevCount => prevCount + 1);Updating Complex State with useReducer
For complex state logic where the next state depends on multiple
actions or nested objects, useReducer is the preferred
hook. It works by dispatching actions to a reducer function, which then
determines the new state.
To update state with useReducer, dispatch an action
object containing a type and an optional
payload:
import React, { useReducer } from 'react';
const initialState = { count: 0 };
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
throw new Error();
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<>
<p>Count: {state.count}</p>
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
</>
);
}Triggering Side Effects on Update
When you update a Hook’s state, you often need to run side effects
(such as API calls, subscriptions, or manual DOM manipulations) in
response. The useEffect hook handles this by accepting a
dependency array.
To execute code whenever a specific state value updates, include that state variable in the dependency array:
import React, { useState, useEffect } from 'react';
function UserProfile({ userId }) {
const [userData, setUserData] = useState(null);
useEffect(() => {
// This runs every time 'userId' changes
fetch(`https://api.example.com/user/${userId}`)
.then(res => res.json())
.then(data => setUserData(data));
}, [userId]); // Dependency array
}