Redux là một vùng chứa quản lý trạng thái có thể dự đoán cho các ứng dụng JavaScript, được tạo bởi Dan Abramov vào năm 2015. Redux triển khai luồng dữ liệu một chiều dựa trên kiến trúc Flux: trạng thái được lưu trữ trong một Store duy nhất, chỉ được thay đổi thông qua các hàm Reducer thuần túy và được khởi tạo qua Action với Dispatch. Theo npm Trends, Redux duy trì hơn 7 triệu lượt tải xuống hàng tuần, vẫn là tiêu chuẩn cho quản lý trạng thái trong React Native và ứng dụng web.
Điểm chính
Redux là một mẫu kiến trúc và thư viện quản lý trạng thái, dựa trên ba nguyên tắc: nguồn sự thật duy nhất, trạng thái chỉ đọc và thay đổi thông qua các hàm thuần túy. Không giống như MVC, nơi mô hình có thể thay đổi trạng thái không thể dự đoán, Redux đảm bảo tính tất định: với cùng dữ liệu đầu vào, kết quả luôn giống nhau.
Redux được lấy cảm hứng từ kiến trúc Flux của Facebook và ngôn ngữ Elm. Sự khác biệt chính so với Flux là một Store duy nhất thay vì nhiều Store. Trong Redux, tất cả trạng thái ứng dụng — đối tượng, mảng, cờ tải — được lưu trữ trong một cây duy nhất. Điều này đơn giản hóa việc gỡ lỗi, kiểm tra và gỡ lỗi du hành thời gian. Nhà phát triển có thể lưu toàn bộ Store, phát lại một chuỗi Action và xem trạng thái đã thay đổi như thế nào ở mỗi bước.
Theo khảo sát State of JS 2025, 68% người trả lời sử dụng quản lý trạng thái chọn Redux hoặc Redux Toolkit. Công cụ này được hỗ trợ bởi tất cả các framework hiện đại: React, React Native, Angular, Vue và thậm chí cả JavaScript thuần không có framework.
Luồng dữ liệu một chiều là nguyên tắc chính của Redux, nơi dữ liệu di chuyển nghiêm ngặt theo một hướng: View → Action → Dispatch → Reducer → Store → View. Không thành phần nào có thể thay đổi Store trực tiếp. View chỉ đăng ký thay đổi qua useSelector hoặc connect và khởi tạo thay đổi qua dispatch.
Chu kỳ làm việc của Redux: người dùng nhấp vào nút → thành phần gọi dispatch({ type: 'INCREMENT' }) → Store chuyển Action đến Root Reducer → Reducer tính toán trạng thái mới → Store thông báo cho người đăng ký → View hiển thị lại với dữ liệu mới. Chu kỳ này đảm bảo rằng mọi thay đổi đều có nguyên nhân rõ ràng dưới dạng một Action cụ thể.
DevTools — công cụ tích hợp của Redux để giám sát mọi Action, trạng thái Store và thời gian thực thi. Nhà phát triển thấy danh sách tất cả các Action đã được gửi, sự khác biệt trạng thái (diff) trước và sau, và có thể quay lại bất kỳ trạng thái trước đó. Điều này làm cho việc gỡ lỗi trạng thái phức tạp nhanh hơn hàng chục lần so với ghi nhật ký thông thường.
Store — một đối tượng chứa toàn bộ cây trạng thái ứng dụng. Được tạo qua configureStore (RTK) hoặc createStore. Store cung cấp ba phương thức: getState() để đọc, dispatch(action) để thay đổi và subscribe(listener) để đăng ký. Trong Redux Toolkit, Store đã bao gồm middleware, DevTools và hỗ trợ slice.
import { configureStore } from '@reduxjs/toolkit'
interface CounterState {
value: number
}
const initialState: CounterState = { value: 0 }
function counterReducer(
state = initialState,
action: { type: string }
): CounterState {
switch (action.type) {
case 'INCREMENT':
return { value: state.value + 1 }
default:
return state
}
}
const store = configureStore({ reducer: counterReducer })
store.dispatch({ type: 'INCREMENT' })
console.log(store.getState()) // { value: 1 }Action và Action Creator — Action là một đối tượng có trường bắt buộc type (hằng chuỗi) và payload tùy chọn (dữ liệu). Action Creator là hàm trả về một Action. Trong Redux Toolkit, createAction được sử dụng để tạo Action với kiểu tự động.
Reducer — một hàm thuần túy nhận trạng thái hiện tại và Action, trả về trạng thái mới. Reducer không được: thay đổi trạng thái (trả về đối tượng mới), gọi API, tạo số ngẫu nhiên hoặc truy cập Date. Tính bất biến được đảm bảo thông qua toán tử spread ... hoặc Immer (được tích hợp trong RTK).
| Thành phần | Trách nhiệm | Ràng buộc |
|---|---|---|
| Store | Lưu trữ trạng thái, dispatch, subscribe | Một mỗi ứng dụng |
| Action | Mô tả ý định thay đổi trạng thái | Phải có type |
| Reducer | Tính toán trạng thái mới | Hàm thuần túy, không tác dụng phụ |
| Dispatch | Gửi Action đến Reducer | Đồng bộ theo mặc định |
| Selector | Trích xuất dữ liệu từ Store | Ghi nhớ qua createSelector |
Middleware là một chuỗi các hàm được chèn giữa lời gọi dispatch và thời điểm Action đến Reducer. Mỗi middleware nhận Store API và có thể ghi nhật ký, sửa đổi, trì hoãn hoặc hủy Action. Redux Thunk là middleware tiêu chuẩn cho các thao tác bất đồng bộ, cho phép gửi hàm thay vì đối tượng.
import { createAsyncThunk } from '@reduxjs/toolkit'
export const fetchUser = createAsyncThunk(
'users/fetchById',
async (userId: number, { rejectWithValue }) => {
const response = await fetch(`/api/users/${userId}`)
if (!response.ok)
return rejectWithValue('Failed to fetch')
return await response.json()
}
)Các middleware phổ biến: Redux Thunk — cho các cuộc gọi bất đồng bộ đơn giản, Redux Saga — cho các kịch bản phức tạp với saga generator (debounce, race, yêu cầu song song), Redux Observable — dựa trên RxJS cho luồng phản ứng. Trong Redux Toolkit, middleware được kết nối qua tham số middleware trong configureStore.
Theo khảo sát State of JS 2025, Thunk được sử dụng trong 72% dự án Redux, Saga trong 18% và Observable trong 5%. Đối với hầu hết ứng dụng, sự kết hợp Thunk + RTK Query đủ để bao phủ 95% luồng công việc dữ liệu bất đồng bộ.
Redux Toolkit (RTK) là cách chính thức và được khuyến nghị để viết logic Redux, được phát hành vào năm 2019. RTK bao gồm configureStore, createSlice, createAsyncThunk và createEntityAdapter, giảm boilerplate Redux xuống 60-70%. Thay vì tạo Action Creator, Reducer và kiểu thủ công, một createSlice duy nhất được sử dụng.
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
const counterSlice = createSlice({
name: 'counter',
initialState: { value: 0 },
reducers: {
increment(state) { state.value += 1 },
incrementByAmount(state, action: PayloadAction<number>) {
state.value += action.payload
}
}
})
export const { increment, incrementByAmount } = counterSlice.actions
export default counterSlice.reducerRTK Query là một giải pháp tích hợp để làm việc với API dựa trên Redux Toolkit. Nó cho phép định nghĩa endpoint một cách khai báo qua createApi với tự động tạo hook, lưu đệm, vô hiệu hóa thẻ và cập nhật lạc quan. RTK Query thay thế việc viết thủ công Thunk, Reducer và Selector cho mọi yêu cầu API.
Entity Adapter — tiện ích createEntityAdapter để chuẩn hóa các bộ sưu tập thực thể. Cung cấp reducer CRUD tích hợp, selector và sắp xếp cho mảng đối tượng. Nếu Store chứa danh sách người dùng, sản phẩm hoặc đơn hàng — Entity Adapter giảm mã reducer xuống 80%.
React Native Redux là stack tiêu chuẩn cho ứng dụng di động trong JavaScript. Redux tích hợp qua Provider từ react-redux, bao bọc thành phần gốc của ứng dụng. Các hook useSelector và useDispatch cung cấp cho thành phần quyền truy cập trạng thái mà không cần props drilling. Persist — redux-persist lưu Store vào AsyncStorage hoặc MMKV, khôi phục trạng thái sau khi khởi động lại ứng dụng.
Middleware cho React Native: redux-flipper để gỡ lỗi qua Flipper, redux-observable cho luồng phản ứng với trình điều khiển gốc, react-native-mmkv cho lưu trữ bền vững nhanh. Plugin điều hướng redux-first-router kết nối màn hình với Store, cho phép khôi phục trạng thái màn hình khi quay lại.
Trong React Native, Redux được sử dụng cùng với chiến lược network-first: ứng dụng đầu tiên cố gắng tải dữ liệu từ máy chủ, sau đó lưu đệm vào Store qua RTK Query hoặc redux-persist. Chế độ ngoại tuyến đạt được bằng cách kết hợp Redux + NetInfo + hàng đợi Action để gửi lại khi kết nối được khôi phục.
Câu hỏi thường gặp
Redux là giải pháp đầy đủ tính năng với Store, DevTools, Middleware và trạng thái bất biến. Context API là cơ chế tích hợp của React để truyền dữ liệu mà không cần props drilling. Context phù hợp cho chủ đề toàn cục và bản địa hóa, trong khi Redux dành cho trạng thái phức tạp với thao tác bất đồng bộ, lưu đệm và gỡ lỗi. Trong ứng dụng lớn, Context gây ra việc hiển thị lại không cần thiết, trong khi Redux với selector giải quyết vấn đề này.
Immer là thư viện quản lý trạng thái bất biến, được tích hợp trong Redux Toolkit. Immer cho phép viết reducer như thể đang thay đổi trạng thái trực tiếp: state.value += 1. Bên trong, Immer tạo đối tượng proxy (draft), theo dõi thay đổi và trả về đối tượng bất biến mới. Điều này giảm khối lượng mã reducer xuống 50% và loại bỏ các thay đổi ngẫu nhiên.
Logic Redux được kiểm tra riêng biệt: Reducer — hàm thuần túy, chỉ cần gọi với các Action khác nhau và kiểm tra kết quả. Action Creator — xác minh đối tượng trả về. Thunk — giả lập API, gọi dispatch và kiểm tra Action nào đã được gửi. Thành phần với useSelector — sử dụng Provider với Store kiểm tra trong trình kết xuất. Redux DevTools giúp viết kiểm tra bằng cách phát lại chuỗi Action từ phiên thực tế.
useState đủ cho trạng thái cục bộ của một thành phần: văn bản trường, mở/đóng modal. Redux cần thiết khi trạng thái được chia sẻ giữa nhiều màn hình, yêu cầu đồng bộ bất đồng bộ (dữ liệu từ máy chủ), cần duy trì giữa các lần khởi động lại ứng dụng (persist) hoặc yêu cầu gỡ lỗi du hành thời gian. Đối với ứng dụng nhỏ, Redux là quá mức — hãy sử dụng Context + useReducer thay thế.
Normalizr là thư viện chuẩn hóa dữ liệu lồng nhau thành cấu trúc Store phẳng. Thay vì lưu trữ đối tượng sâu như user.posts[0].comments, chuẩn hóa tạo từ điển: entities.users, entities.posts, entities.comments với tham chiếu theo ID. Điều này đơn giản hóa việc cập nhật một thực thể duy nhất ở mọi nơi và tăng tốc selector. Redux Toolkit khuyến nghị dữ liệu chuẩn hóa cho các mô hình phức tạp.
Tổng kết
Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay
IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.
Đọc thêm