Mục lục

State Management Fundamentals: State, Props & Context

Khi nào dùng State? Khi nào dùng Props? Và khi nào thực sự cần tới Context hay Global State? Quy tắc 'Lift State Up' và tránh 'Prop Drilling'.

Quản lý trạng thái (State) là linh hồn của ứng dụng React. Làm chủ việc đặt state ở đâu (State Placement) sẽ giúp ứng dụng của bạn mượt mà và dễ bảo trì.

1. Local State (useState / useReducer)

Dùng cho dữ liệu chỉ mình Component đó quan tâm.

  • Ví dụ: Trạng thái đóng/mở của một Modal, nội dung đang gõ trong Input, tab đang được chọn.
  • Quy tắc: Giữ state gần nhất với nơi sử dụng (Keep state local). Đừng vứt mọi thứ vào Global State.

2. Lifting State Up (Nâng State lên cao)

Khi hai hoặc nhiều Component anh em cần chia sẻ cùng một dữ liệu.

  • Giải pháp: Tìm component cha chung gần nhất, đặt state ở đó và truyền xuống cho các con qua Props.
tsx:
function Parent() {
  const [activeTab, setActiveTab] = useState('home');
  return (
    <>
      <Tabs onSelect={setActiveTab} />
      <Content current={activeTab} />
    </>
  );
}

3. Prop Drilling (Vấn đề nảy sinh)

Khi bạn phải truyền Props qua quá nhiều tầng trung gian (từ Ông -> Cha -> Con -> Cháu) mà các tầng ở giữa không hề dùng dữ liệu đó.

  • Hậu quả: Code bị rối, khó refactor, component trung gian bị "ô nhiễm" bởi những props không cần thiết.

4. React Context API: Giải pháp cho Prop Drilling

Context cung cấp một "đường ống ngầm" (Pipe) để truyền dữ liệu xuyên qua các tầng mà không cần qua Props.

  • Khi nào dùng: Những dữ liệu mang tính "toàn cục" (Global) hoặc dùng ở rất nhiều nơi sâu trong cây component.
  • Ví dụ: Theme (Dark/Light), User Thông tin đăng nhập, Ngôn ngữ (i18n).
tsx:
// 1. Tạo Context
const ThemeContext = createContext('light');

// 2. Wrap Provider ở tầng cao (thường là Layout/App)
<ThemeContext.Provider value="dark">
  <DeeplyNestedComponent />
</ThemeContext.Provider>

// 3. Sử dụng ở tầng sâu
const theme = useContext(ThemeContext);

5. Server State vs UI State (Tư duy Senior)

Đây là sự phân chia quan trọng nhất mà nhiều người thường bỏ qua:

  • Server State: Dữ liệu từ API (List sản phẩm, Profile user).
    • Công cụ nên dùng: React Query (TanStack Query) hoặc SWR.
  • UI State: Trạng thái giao diện (Sidebar toggle, Loading spinner).
    • Công cụ nên dùng: useState, Context hoặc Zustand.

Lời khuyên: Đừng bao giờ dùng Redux/Zustand để lưu trữ dữ liệu API. Hãy dùng React Query để quản lý Caching/Fetching, và chỉ dùng Global State cho các trạng thái giao diện phức tạp.

6. Derived State (Dữ liệu dẫn xuất)

Đừng tạo state mới cho những dữ liệu có thể tính toán được.

tsx:
// ❌ SAI: Tạo 2 state đồng bộ
const [items, setItems] = useState([]);
const [total, setTotal] = useState(0); 

// ✅ ĐÚNG: Tính toán ngay trong render
const total = items.reduce((sum, i) => sum + i.price, 0);

Kết luận

  1. Ưu tiên Local State.
  2. Nếu cần chia sẻ -> Lift State Up.
  3. Nếu Prop Drilling quá sâu -> Context API.
  4. Nếu dữ liệu từ API -> React Query.
  5. Chỉ dùng Zustand/Redux khi ứng dụng thực sự lớn và UI state quá phức tạp.
Quảng cáo
mdhorizontal