Zustand: Thư viện quản lý state React nhỏ gọn và mạnh mẽ

Zustand là gì và tại sao nên dùng

Zustand là thư viện quản lý state cho React, được tạo bởi Daishi Kato thuộc tổ chức pmndrs (cùng team với react-three-fiber). Tên gọi lấy từ tiếng Đức có nghĩa “căn phòng”, mascot là một chú gấu nâu dễ thương. Tính đến nay Zustand đã thu hút hơn 58.000 stars trên GitHub và có hơn 198 triệu lượt tải về mỗi tháng trên npm, xếp thứ hai chỉ sau Redux về lượng sử dụng trong hệ sinh thái React.

Vấn đề lớn nhất của state management trong React là sự phức tạp. Redux yêu cầu bạn viết actions, reducers, action types, và thường cần Provider bao quanh toàn bộ ứng dụng. Context API đơn giản hơn nhưng lại gây re-render toàn bộ subtree khi giá trị thay đổi. Zustand giải quyết cả hai vấn đề này bằng cách cung cấp một API cực kỳ gọn nhẹ dựa trên React hooks, không cần Provider, không cần boilerplate.

Giao diện code editor hiển thị cách tạo Zustand store với hàm create và hook useCounterStore trong React

Cài đặt và cấu hình cơ bản

Việc cài đặt Zustand cực kỳ đơn giản. Thư viện không có bất kỳ dependency nào (v5), nghĩa là bundle size gần như bằng không so với các giải pháp khác.

npm install zustand

Sau khi cài đặt, bạn có thể tạo store đầu tiên chỉ với vài dòng code:

import { create } from 'zustand'

const useCounterStore = create((set) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
  decrement: () => set((state) => ({ count: state.count - 1 })),
  reset: () => set({ count: 0 }),
}))

Điểm đặc biệt nhất: bạn không cần bọc ứng dụng trong Provider nào cả. Store là một React hook, dùng trực tiếp trong component bằng cách gọi useCounterStore.

function Counter() {
  const count = useCounterStore((state) => state.count)
  const increment = useCounterStore((state) => state.increment)
  return (
    <div>
      <span>{count}</span>
      <button onClick={increment}>Tăng</button>
    </div>
  )
}

Selector và tối ưu hiệu năng re-render

Một trong những điểm mạnh nhất của Zustand là cơ chế selector. Mỗi component chỉ re-render khi phần state mà nó chọn thay đổi. Ví dụ trên, component Counter chỉ re-render khi count thay đổi, hoàn toàn không bị ảnh hưởng nếu các phần khác trong store thay đổi.

Để so sánh, nếu dùng Context API, mọi component consuming cùng context sẽ re-render khi bất kỳ giá trị nào trong context thay đổi. Zustand tránh được vấn đề này bằng cách sử dụng strict equality comparison (old === new).

Đối với trường hợp cần chọn object hoặc array phức tạp, Zustand cung cấp hook useShallow để so sánh theo shallow equality, tránh re-render không cần thiết:

import { useShallow } from 'zustand/react/shallow'

const { bears, fishes } = useStore(
  useShallow((state) => ({ bears: state.bears, fishes: state.fishes }))
)

Biểu đồ so sánh mức độ phổ biến giữa các thư viện quản lý state Zustand, Redux Toolkit và Jotai

Middleware mạnh mẽ

Zustand cung cấp hệ thống middleware linh hoạt thông qua zustand/middleware. Đây là nơi thư viện thực sự tỏa sáng so với các đối thủ:

  • Persist: Tự động lưu state vào localStorage hoặc sessionStorage. Chỉ cần bọc store với persist middleware, toàn bộ state sẽ được lưu lại ngay cả khi refresh trang.
  • Devtools: Tích hợp trực tiếp với Redux DevTools extension, cho phép time-travel debugging mà không cần cấu hình phức tạp.
  • Immer: Cho phép viết state update theo kiểu mutable (sử dụng Immer bên dưới), code ngắn hơn đáng kể.
  • Redux: Nếu bạn muốn viết theo kiểu reducer-action, Zustand vẫn hỗ trợ thông qua redux middleware.

Ví dụ kết hợp persist và devtools:

import { create } from 'zustand'
import { persist, devtools } from 'zustand/middleware'

const useStore = create(
  devtools(
    persist(
      (set, get) => ({
        theme: 'light',
        setTheme: (theme) => set({ theme }),
      }),
      { name: 'app-settings' }
    )
  )
)

API ngoài component

Zustand không giới hạn bạn trong hệ thống React hooks. Bạn có thể đọc và ghi state từ bất kỳ đâu trong JavaScript thuần, rất hữu ích cho service layers, utility functions, hoặc testing:

// Đọc state
const currentCount = useCounterStore.getState().count

// Ghi state
useCounterStore.setState({ count: 10 })

// Lắng nghe thay đổi
const unsubscribe = useCounterStore.subscribe(
  (state) => console.log('State changed:', state)
)

So sánh Zustand với Redux Toolkit và Jotai

Tiêu chí Zustand Redux Toolkit Jotai
Boilerplate Rất ít Trung bình Rất ít
Provider Không cần Cần Cần
Mô hình Flux (1 store) Flux (1 store) Atomic (nhiều atom)
TypeScript Hỗ trợ tốt Hỗ trợ tốt Hỗ trợ tốt
DevTools Có (middleware) Có (native) Có (middleware)
Persist Có (middleware) Có (redux-persist) Có (atomWithStorage)

Jotai và Zustand đều do Daishi Kato tạo ra, nhưng phục vụ mục đích khác nhau: Zustand phù hợp cho flux-style state management (một store tập trung), trong khi Jotai phù hợp cho atomic state (nhiều atom nhỏ riêng biệt, tự động cập nhật).

Khi nào nên và không nên dùng Zustand

  • Nên dùng: Ứng dụng trung bình đến lớn cần state dùng chung giữa nhiều component không liên quan. Muốn hiệu năng re-render tối ưu mà không cần cấu hình phức tạp. Cần persist state vào localStorage. Muốn debug dễ dàng với Redux DevTools.
  • Không nên dùng: State chỉ dùng trong một component (useState đủ đơn giản). App cần kiến trúc Redux chuẩn với time-travel debugging nghiêm ngặt (Redux Toolkit vẫn tốt hơn). Ứng dụng sử dụng React Server Components (Next.js 13+) — store có thể gây bug và lộ privacy dữ liệu.

Zustand đại diện cho triết lý “ít code hơn, làm được nhiều hơn” trong hệ sinh thái React. Với hơn 50 triệu lượt tải mỗi tuần, đây là một trong những lựa chọn state management phổ biến nhất hiện nay và xứng đáng là lựa chọn đầu tiên cho bất kỳ dự án React nào.

Tham khảo thêm

Tôi là một lập trình viên IOS. Code chính là IOS nhưng thỉnnh thoảng vẫn đá sang Android hoặc web. Mặc dù không quá thông thạo nhưng tôi sẽ chia sẻ những kiến thức mà mình đã tìm hiểu, áp dụng qua.

Bài viết liên quan

SQLite là gì? Hướng dẫn cơ sở dữ liệu nhúng cho người mới

SQLite là gì? Đây là cơ sở dữ liệu SQL nhẹ nhàng nhất thế giới, được sử dụng trong mọi smartphone, trình duyệt web và hàng tỷ ứng dụng trên…

Xem thêm

FastAPI là gì? Framework Python hiện đại cho lập trình viên

FastAPI là gì? Framework Python hiện đại cho API hiệu năng cao FastAPI là framework Python hiện đại dành cho việc xây dựng API, nổi bật nhờ hiệu năng cao…

Xem thêm

Prisma là gì? Hướng dẫn ORM cho Node.js và TypeScript

Prisma là gì? Prisma là một ORM (Object-Relational Mapping) mã nguồn mở thế hệ mới dành cho Node.js và TypeScript, giúp lập trình viên làm việc với cơ sở dữ…

Xem thêm
0 0 đánh giá
Article Rating
Theo dõi
Thông báo của
guest
0 Comments
Cũ nhất
Mới nhất Được bỏ phiếu nhiều nhất