React状态管理库—— zustand 为啥这么简单易用🚀
大约 4 分钟
文章同步在公众号:萌萌哒草头将军,欢迎关注
 🚀 简单易用的 zustand 
🚀 简单的对比
说到中大型 React 项目状态管理库,最先想到就是 Redux。而 Redux 是基于 Flux 架构模式的状态管理库。
Redux 继承了 Flux"单向流动"的特点,
- 用户与 View 进行交互,触发相应的 Actions。
 - Actions 通过 Dispatcher 进行派发。
 - Stores 接收派发的 Actions,并根据需要更新状态。
 - Stores 更新后触发事件,通知 Views 进行界面更新。
 - Views 使用 Stores 中的最新状态重新渲染界面。
 
然而随着 Hook 的流行,Flux 模式显得日益笨重。在很长时间里,通常会采用 react 自带的 createContext 代替 Redux 的需求。一个简单的例子如下。
import React, { createContext, useContext, useState } from 'react';
// 创建一个上下文对象类型
interface CountContextProps {
  count: number;
  setCount: (count: number) => void;
}
// 创建上下文
const CountContext = createContext<CountContextProps | undefined>(undefined);
// 提供器组件
const CountProvider: React.FC = ({ children }) => {
  const [count, setCount] = useState(0);
  const contextValue: CountContextProps = {
    count,
    setCount,
  };
  return (
    <CountContext.Provider value={contextValue}>
      {children}
    </CountContext.Provider>
  );
};
// 消费者组件
const Counter: React.FC = () => {
  const { count, setCount } = useContext(CountContext)!;
  const increment = () => {
    setCount(count + 1);
  };
  const decrement = () => {
    setCount(count - 1);
  };
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
      <button onClick={decrement}>Decrement</button>
    </div>
  );
};
// 应用程序组件
const App: React.FC = () => {
  return (
    <CountProvider>
      <Counter />
    </CountProvider>
  );
};
export default App;
虽然是个简单的例子,但是实际开发中,步骤 i 依然繁琐。
那么有没有更简便的方案?答案是肯定的!
那就是 zustand 。同样功能的例子实现如下:
import create from "zustand";
// 创建状态存储
interface CountState {
  count: number;
  increment: () => void;
  decrement: () => void;
}
const useCountStore =
  create <
  CountState >
  ((set) => ({
    count: 0,
    increment: () => set((state) => ({ count: state.count + 1 })),
    decrement: () => set((state) => ({ count: state.count - 1 })),
  }));
// 消费者组件
const Counter: React.FC = () => {
  const { count, increment, decrement } = useCountStore();
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
      <button onClick={decrement}>Decrement</button>
    </div>
  );
};
// 应用程序组件
const App: React.FC = () => {
  return <Counter />;
};
export default App;
简单的对比,就可以发现 zustand 没有特定的概念,简单易用。
🚀 监听变化
通常,当 store 变化时,可以使用 useEffect 监听状态变化
// 消费者组件
const Counter: React.FC = () => {
  const { count, increment, decrement } = useCountStore();
  useEffect(() => console.log(count), [count]);
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
      <button onClick={decrement}>Decrement</button>
    </div>
  );
};
但是如果当状态的变化不想引起组件的渲染时,可以使用如下方式:
// 消费者组件
const Counter: React.FC = () => {
  const { count, increment, decrement } = useCountStore();
  // useEffect(() => console.log(count), [count])
  // 注意,useCountStore.subscribe的返回值时取消订阅函数
  // 所以当组件卸载时,会自动取消订阅
  useEffect(
    () => useCountStore.subscribe((state) => console.log(state.count)),
    []
  );
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
      <button onClick={decrement}>Decrement</button>
    </div>
  );
};
🚀 中间件模式
zustand 还在状态管理的功能上提供了中间件功能。例如,当对应的值发生变化时,自动更新localStroge
const log = (config) => (set, get, api) =>
  localStroge(
    (...args) => {
      // 这里args为set({ count })的参数就{ count }
      localStroge.setItem("count", args.count);
      set(...args);
    },
    get,
    api
  );
const useCountStore = create(
  localStroge((set) => ({
    count: 0,
    setCount: (count) => set({ count }),
  }))
);
当然,zustand提供了内置的一些中间件,如下:
export * from "./middleware/redux.ts";
export * from "./middleware/devtools.ts";
export * from "./middleware/subscribeWithSelector.ts";
export * from "./middleware/combine.ts";
export * from "./middleware/persist.ts";
🚀 总结
zustand 凭借小巧的体积(2kb)和简单易用的特性,迅速获得 GitHub 34.3k 的 star,足以说明它的好用。
好了今天的文章分享到这了,下篇文章我们从源码的角度进一步的认识 zustand !
