First of all, it is necessary to understand the functionality of these hooks. In the next minutes, I try to summarize the principal functionalities for each one, and then describe their applications and recommendations.
useState
This hook permits us to add a state variable in our component, it returns a stateful value and a function to update that value, providing a simple way to introduce stateful logic into functional components.
This hook is typically used for managing simpler state needs within components.
Sintaxis
const [state, setState] = useState(initialValue);
initialValue
: the value you want the state to be initially.
state
: in the first render, it is equal to initialValue
you have passed
setState
: function to update value and trigger a re-render
Example:
The Counter changes when pressing the button, this action shoots an update function and changes the value state.
import { useState } from 'react'
export function Counter() {
const [count, setCount] = useState(0)
return (
<div>
<span>Value count: {count}</span>
<button onClick={() => setCount(count + 1)}>
+1
</button>
</div>
)
}
useReducer
On the other hand, useReducer
is used for managing complex state login within functional components. It takes in a reducer function and an initial state and returns the current state and a dispatch function to trigger state transitions.
Sintaxis
const [state, dispatch] = useReducer(reducer, initialValue, init?);
reducer
: reducer function that specifies how the state gets updated
initialValue
: value employed to initially calculate
init
: this value is optional, it is an initializer function that should return the initial state
state
: current state. In the first render, it is set with the initialValue
or init
dispatch
: the dispatch function updates the state to a different value and triggers a re-render
Example:
We modified the later example and now we use useReducer
hook for changing the counter value in our component.
import { 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 (
<div>
<p>You clicked {state.count} times</p>
<button onClick={() => dispatch({ type: 'increment' })}>
Increment
</button>
<button onClick={() => dispatch({ type: 'decrement' })}>
Decrement
</button>
</div>
);
}
When to use each one?
useState
is typically used for managing simpler state needs where the state transitions are straightforward and is good for managing independent pieces of state. It's simpler to use and understand, especially for beginners.
useReducer
is often preferred when state management logic becomes more complex or when multiple actions need to be handled in a single stateful entity within a component.
useReducer
is inspired by Redux, a predictable state container for JavaScript apps, and it offers a similar API.Recommendation
In some cases is necessary to use a useEffect
hook when using these hooks to prevent re-renders in your project.