Written on 27th December 2025 by Carter Phan.
useReducer là phiên bản nâng cấp của useState và cách thức hoạt động của nó giống với Reducer trong Redux thì useReducer cũng nhận vào một reducer dạng (state, action) và trả ra một newState. Khi sử dụng chúng ta sẽ nhận được một cặp bao gồm current state và dispatch function.
useReducer:
// Tạo 1 hàm init động để thực hiện Lazy initialization
const init = (initialCount) => {count: initialCount}
// Khai báo 1 reducer và định nghĩa các logic thực hiện ứng với mỗi loại action
const reducer = (state, action) {
switch (action.type) {
case 'INCREMENT':
return {count: state.count + 1}
case 'DECREMENT':
return {count: state.count - 1}
case 'RESET':
return init(action.payload)
default:
throw new Error()
}
}
const Counter = ({ initialCount }) => {
/*
* useReducer ở đây nhận đầu vào lần lượt 3 tham số là:
* 1. reducer đã được định nghĩa trước đó
* 2. Giá trị khởi tạo ban đầu initialCount
* 3. Hàm init để trả về initialState đối với giá trị khởi tạo ban đầu
*
* Có thể truyền initialState trực tiếp mà không cần hàm init
* useReducer(reducer, initialState)
*
* useReducer trả về 1 mảng gồm:
* 1. state là biến chứa giá trị hiện tại của state
* 2. dispatch là hàm kích hoạt một action nào đó trong reducer để thay đổi state
*/
const [state, dispatch] = useReducer(reducer, initialCount, init)
return (
<>
Count: {state.count}
<button
onClick={() => dispatch({type: 'RESET', payload: initialCount})}
>
Reset
</button>
<button onClick={() => dispatch({type: 'DECREMENT'})}>-</button>
<button onClick={() => dispatch({type: 'INCREMENT'})}>+</button>
</>
)
}
Khi mà App có quy mô nhỏ, không nhiều state và chỉ muốn chia sẻ state giữa các Component thì hoàn toàn có thể sử dụng useContext để thay thế cho Redux.
Còn nếu App cần phải xử lý nhiều logic phức tạp thì lúc này nên dùng sagas hoặc là middleware của Redux. Ngoài ra Redux còn cung cấp cho chúng ta một vài lợi thế quan trọng: