zustand 快速上手
zustand 和 redux 相比,有何优缺点
在前些年react redux 流行的时候, zustand 能获得认可,肯定是有可取之处的,大致过了一遍官方文档,总结下来有一下优点:
- 轻量级框架
- 配置简单
- api 少但是功能全
- 心智负担少,像编写 util 方法一样去编写store
轻量和灵活性既是 zustand 的优点,但是也导致了他的缺点,个人认为最大的缺点是没有范式,不同人封装出来的 zustand 很可能不一样,redux 可能配置复杂,但是有统一的范式,不同项目,不同人封装出来的 store,总体上不会差很远。
安装
直接安装最新版
1npm i zustand 2
基本的使用方式
基本的使用方式包含三个常见的步骤
- 创建 store
- 在组件中使用 store
- 基于slice思想,拆分和组合 store
对于大部分项目,了解完这几个概念足够了
创建 store
这里使用的 ts,js 用法大同小异,可参考官方文档配置
1// store.ts 2import {create} from "zustand"; 3type BearState={ 4 bears:number, 5} 6type BearAction={ 7 increase:()=>void, 8 decrease:()=>void, 9} 10type BearStore=BearState & BearAction; 11const useBear=create<BearStore>()(set=>({ 12 bears:0, 13 increase:()=>set(state=>({bears:state.bears+1})), 14 decrease:()=>set(state=>({bears:state.bears-1})), 15})) 16export default useBear; 17
zustand 将 state 和 action 放在一个对象中,基础的数据类型表示 state,函数表示 action,通过 set 来更新数据
在组件中使用 store
直接通过 create 返回的 hook 来访问 store
注意:zustand 和 redux 相比,在组件中使用时,不用在跟组件中通过provider 来注入 store ,这也是 zustand 强大的地方之一
1import useBear from "./store"; 2function App() { 3 const bears = useBear(state=>state.bears); 4 const increase = useBear(state=>state.increase); 5 console.log(bears) 6 return ( 7 <div> 8 <h1>{bears}</h1> 9 <button onClick={increase}>Increase</button> 10 </div> 11 ); 12} 13
为了精确控制页面的刷新,应该通过 state=>state.bears 的形式来访问数据,这样可以防止因其他状态改变而引起的组件刷新
当 store 中的 bears 发生改变时,组件会自动重新渲染
拆分和组合 store
熟悉 redux 最新版的一定会知道,redux 的 createSlice,用于拆分 store,zustand 没有提供这样的 api ,但是可以通过 slice 的形式来实现类似的功能。
- 创建第一个 slice
1// fishSlice.ts 2export const createFishSlice = (set) => ({ 3 fishes: 0, 4 addFish: () => set((state) => ({ fishes: state.fishes + 1 })), 5}) 6 7
- 创建第二个 slice
1// bearSlice.ts 2export const createBearSlice = (set) => ({ 3 bears: 0, 4 addBear: () => set((state) => ({ bears: state.bears + 1 })), 5 eatFish: () => set((state) => ({ fishes: state.fishes - 1 })), 6}) 7
- 组合 slice
1import { create } from 'zustand' 2import { createBearSlice } from './bearSlice' 3import { createFishSlice } from './fishSlice' 4 5export const useBoundStore = create((...a) => ({ 6 ...createBearSlice(...a), 7 ...createFishSlice(...a), 8})) 9 10
通过将 set 传递给 slice 实现 store 的拆分和组合
总结
zustand 十分简单和灵活,他不像 redux 一样需要在根组件中全局注入 store ,才能在子组件中使用,zustand 创建的 store 可以像组件一样导出给其他模块使用,但是 store 封装质量依靠开发者自身的水平,不同水平的开发者封装出来的 store 可能形态各异。
想了解更多 zustand api,例如中间件、性能优化或最佳实践等,可以阅读官方文档