![]()
Ở bài trước, chúng ta đã học cách ghi nhớ dữ liệu vào ổ cứng điện thoại bằng AsyncStorage. Nhưng đó là dữ liệu lưu trữ lâu dài. Vậy còn những dữ liệu cần phản hồi ngay lập tức trên màn hình trong lúc người dùng đang thao tác thì sao?
Hãy tưởng tượng một kịch bản vô cùng quen thuộc: Bạn đang làm một ứng dụng mua sắm. Ở trang Chi tiết sản phẩm, người dùng bấm nút "Thêm vào giỏ hàng". Ngay lập tức, biểu tượng Giỏ hàng nằm ở tít trên góc phải của thanh Header (thuộc một màn hình hoàn toàn khác) phải hiển thị số 1.
Làm thế nào để hai màn hình không liên quan gì đến nhau lại có thể "nháy mắt" và truyền dữ liệu cho nhau trong chớp nhoáng? Chào mừng bạn đến với thế giới của Global State (Quản lý trạng thái toàn cục)!
1. Nỗi đau mang tên "Prop Drilling"
Nếu chỉ dùng useState như ở những bài học đầu tiên, dữ liệu của bạn chỉ sống bên trong một Component duy nhất. Để chia sẻ dữ liệu đó cho một Component khác, bạn phải truyền nó qua các thuộc tính (Props) từ cha xuống con.

Khi ứng dụng lớn lên, cây thư mục của bạn có thể sâu đến 5-6 tầng. Việc bạn phải truyền một biến cartCount từ App ➔ Home ➔ List ➔ Item ➔ Button chỉ để thằng cháu chắt ở dưới cùng sử dụng được gọi là Prop Drilling (Khoan giếng truyền prop).
Điều này biến code của bạn thành một mớ bòng bong cực kỳ khó bảo trì. Cứ mỗi lần sửa tên biến, bạn phải đi sửa lại ở 6 file khác nhau!
2. Giải pháp: "Đám mây" Global State
Để chấm dứt nỗi đau này, các kỹ sư phần mềm đã tạo ra khái niệm Global State (hay còn gọi là Store).
Hãy tưởng tượng Store giống như một trạm phát sóng vô tuyến đặt trên mây, nằm độc lập và cao hơn tất cả các màn hình của bạn.
- Khi nút "Thêm vào giỏ" được bấm, nó bắn một tín hiệu lên trạm phát sóng: "Ê, cộng 1 vào giỏ hàng nhé!"
- Trạm phát sóng cập nhật con số.
- Biểu tượng Giỏ hàng trên Header (đang dò sóng của trạm) ngay lập tức nhận được tín hiệu và tự động cập nhật số
1lên màn hình, bất kể nó nằm ở đâu trong ứng dụng.

Hiện tại, có hai "trạm phát sóng" quyền lực nhất trong giới React Native: Redux Toolkit và Zustand.
3. Redux Toolkit (RTK): Lựa chọn của các dự án lớn
Nhắc đến React, không ai không biết đến Redux. Redux từng bị ghét vì phải viết code thiết lập (boilerplate) quá dài dòng. Nhưng sự ra đời của Redux Toolkit (RTK) đã thay đổi tất cả. RTK là tiêu chuẩn vàng hiện tại, giúp viết Redux nhanh và nhàn hơn gấp 10 lần.

Kiến trúc cốt lõi của Redux
Để hiểu Redux, hãy nghĩ đến cách bạn gửi tiền ở ngân hàng:
- Store (Két sắt): Nơi chứa toàn bộ dữ liệu. Bạn không được tự thò tay vào lấy hay cất tiền.
- Action (Phiếu yêu cầu): Tờ giấy bạn ghi "Tôi muốn nộp 50k".
- Dispatch (Nộp phiếu): Hành động bạn đưa tờ phiếu cho nhân viên ngân hàng.
- Reducer (Nhân viên ngân hàng): Người duy nhất được phép mở két sắt (Store), đọc phiếu (Action) và tính toán lại số tiền của bạn.
Cách cài đặt và sử dụng
Bước 1: Cài đặt
npm install @reduxjs/toolkit react-redux
Bước 2: Tạo một Slice (Một ngăn của Két sắt) Slice là cách RTK gom Action và Reducer lại làm một chỗ cho gọn gàng.
// cartSlice.js
import { createSlice } from '@reduxjs/toolkit'
export const cartSlice = createSlice({
name: 'cart', // Tên của ngăn két
initialState: { count: 0 }, // Dữ liệu ban đầu
reducers: {
// Các nhân viên ngân hàng (hàm xử lý)
addToCart: (state) => {
state.count += 1 // Thêm 1 sản phẩm
},
clearCart: (state) => {
state.count = 0 // Xóa sạch giỏ
},
},
})
export const { addToCart, clearCart } = cartSlice.actions
export default cartSlice.reducer
Bước 3: Sử dụng trong Component
Bất kỳ màn hình nào cũng có thể gọi dữ liệu hoặc thay đổi dữ liệu cực kỳ dễ dàng bằng 2 Hooks: useSelector (để đọc) và useDispatch (để ra lệnh).
import { Text, TouchableOpacity } from 'react-native'
import { useSelector, useDispatch } from 'react-redux'
import { addToCart } from './cartSlice'
export default function ProductButton() {
const dispatch = useDispatch() // Gọi anh nhân viên ngân hàng
return (
<TouchableOpacity onPress={() => dispatch(addToCart())}>
<Text>Thêm vào giỏ</Text>
</TouchableOpacity>
)
}
4. Zustand: Ngôi sao mới nổi (nhanh, gọn, nhẹ)
Dù Redux Toolkit đã rất tốt, nhiều lập trình viên vẫn cảm thấy nó hơi "cồng kềnh" nếu ứng dụng không quá phức tạp. Đó là lúc Zustand (tiếng Đức nghĩa là "Trạng thái") bước lên sàn diễn và lập tức trở thành hiện tượng.

Zustand cắt bỏ hoàn toàn khái niệm Action, Reducer, Provider rườm rà. Nó cho phép bạn tạo một trạm phát sóng chỉ bằng vài dòng code cực thuần React Hooks!
Bước 1: Cài đặt
npm install zustand
Bước 2: Tạo Store trong 1 nốt nhạc
// store.js
import { create } from 'zustand'
export const useCartStore = create((set) => ({
count: 0, // Dữ liệu
addToCart: () => set((state) => ({ count: state.count + 1 })), // Hàm xử lý
clearCart: () => set({ count: 0 }),
}))
Bước 3: Dùng thẳng ở mọi nơi
import { Text, TouchableOpacity } from 'react-native'
import { useCartStore } from './store'
export default function Header() {
// Lấy dữ liệu đếm
const count = useCartStore((state) => state.count)
return <Text>Giỏ hàng: {count}</Text>
}
export function ProductButton() {
// Lấy hàm thêm vào giỏ
const addToCart = useCartStore((state) => state.addToCart)
return (
<TouchableOpacity onPress={addToCart}>
<Text>Thêm vào giỏ</Text>
</TouchableOpacity>
)
}
Tuyệt vời chưa? Không cần bọc ứng dụng trong <Provider>, không cần chia file lằng nhằng. Gọi là chạy!
5. Cuộc chiến lựa chọn: Redux Toolkit hay Zustand?
Bạn đang phân vân không biết nên đưa công cụ nào vào dự án của mình? Đây là lời khuyên thực chiến:
| Tiêu chí | Redux Toolkit | Zustand |
|---|---|---|
| Độ khó học | Khá khó (Nhiều khái niệm) | Cực dễ (Như dùng useState) |
| Lượng code (Boilerplate) | Trung bình - Nhiều | Rất ít |
| Công cụ gỡ lỗi (DevTools) | Xuất sắc, chi tiết từng bước | Tốt, nhưng không mạnh bằng Redux |
| Cộng đồng & Tài liệu | Khổng lồ (Được mọi công ty dùng) | Đang tăng trưởng mạnh mẽ |
| Khi nào nên chọn? | App doanh nghiệp lớn, logic cực kỳ phức tạp, team đông người. | App vừa và nhỏ, làm dự án cá nhân, cần code nhanh và sạch. |
Khuyến nghị cho series học này: Nếu bạn đang học để xin việc tại các công ty lớn, hãy nắm chắc Redux Toolkit vì nó xuất hiện trong 80% JD tuyển dụng. Nếu bạn đang tự làm sản phẩm (Indie hacker) hoặc startup cần ra mắt nhanh, hãy chọn Zustand.
Kết luận: Global State giúp mọi thứ có tổ chức
Global State là chìa khóa để kiến trúc dữ liệu của ứng dụng trở nên gọn gàng, có tổ chức. Nó giải thoát bạn khỏi cơn ác mộng "Prop Drilling", giúp mọi màn hình có thể giao tiếp với nhau theo thời gian thực.
Tuy nhiên, có một bí mật mà ít người mới biết: Cả Redux và Zustand đều RẤT DỞ trong việc quản lý dữ liệu lấy từ API (như xử lý trạng thái Loading, báo lỗi mạng, lưu cache bộ nhớ).
Để giải quyết triệt để vấn đề gọi API, chúng ta sẽ cần đến một "phép màu" mang tên React Query (TanStack Query). Hãy chuẩn bị tinh thần đón xem những bài học thú vị sắp tới nhé!