How to Use useReducer in React
Managing complex state with multiple actions and transitions can become unwieldy with useState. As the creator of CoreUI with over 11 years of React development experience, I use useReducer for sophisticated state management in complex UI components. The useReducer hook provides predictable state updates through a reducer function, similar to Redux but built into React.
Use useReducer to manage complex state logic with a reducer function that handles different action types.
import React, { useReducer } from 'react'
function counterReducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 }
case 'decrement':
return { count: state.count - 1 }
case 'reset':
return { count: 0 }
case 'set':
return { count: action.payload }
default:
throw new Error(`Unknown action: ${action.type}`)
}
}
function Counter() {
const [state, dispatch] = useReducer(counterReducer, { count: 0 })
return (
<div>
<p>Count: {state.count}</p>
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
<button onClick={() => dispatch({ type: 'reset' })}>Reset</button>
<button onClick={() => dispatch({ type: 'set', payload: 100 })}>Set 100</button>
</div>
)
}
The useReducer hook takes a reducer function and initial state, returning current state and a dispatch function. The reducer function receives the current state and an action, then returns the new state. Actions are typically objects with a type property and optional payload. This pattern makes state updates predictable and easier to test compared to multiple useState calls with complex logic.
Best Practice Note:
In CoreUI components, we use useReducer for form validation, data table state management, and complex UI interactions. This approach provides better organization than multiple useState hooks and makes debugging state changes much more straightforward in enterprise applications.



