道阻且长,行而不辍,未来可期
之前只是会使用zustand,也没仔细看过zustand的文档,前段时间一个合约朋友问我前端的zustand怎么用,啊,这,是那个笑起来明媚的不像话的帅哥问我问题诶,那我得认真一下下,尽管已是前同事,还是希望他在异国他乡前程锦绣。
哈哈哈,知识是用来共享的,也希望能帮到 路过的公主 or 王子。
首先看一下Zustand 官方是如何王婆卖瓜的,啊,不,是如何精准的介绍自己的
A small, fast, and scalable bearbones state management solution. Zustand has a comfy API based on hooks. It isn’t boilerplatey or opinionated, but has enough convention to be explicit and flux-like.
小型、快速且可扩展的 bearbones 状态管理解决方案。Zustand 具有基于hooks的舒适 API。
剩下那句叙事,就让他叙吧,继续往下看
嗯,看点实际的,如何使用
Step1:
哦,store是一个hook, 可以在store里面放任何类型的数据:原始类型,对象类型,函数 等。
Set 这个函数用于“合并”状态
Step2:
在组件中使用"store"
你可以在任何地方使用这个hook,不需要Provider.
其实,到这里,zustand–store 的最简单的使用demo已经展示完了。
哈哈哈,想要在众多状态管理库中占有一席之地,总的有自己的长处吧
酒香也怕巷子深,且看zustand是如何表明自己的优势的
Zustand 有很多关于React的状态管理库,在Comparison 页将会进行讨论。将Zustand和Redux,库进行比较
每一个库都有自己的强点和弱点,zustand 官方 将比较一下这些库之间 “不同”和“相似”之处
Zustand VS Redux(不同)
Zustand 和 Redux 十分的相似,他们俩都是基于“不可变”的状态模块。但是Redux要求你的app被redux 的 Provider 所包裹,而 zustand 则不用。
Zustand VS Redux (相似)
在渲染方面,Zustand 和 Redux 是非常的相似。
代码我就不贴啦,这里了解一下Zustand得优势就好啦,想看示例的
网址在这里:https://zustand.docs.pmnd.rs/getting-started/comparison
更新Store的状态
刚刚有提到set是用来合并状态的,既然官方把它单独列出来,又说了一遍,就足以体现它的重要性,那我再说一遍,哈哈哈。
更新Zustand 的状态非常简单,调用 它 提供的set方法就可以了。set方法拥有新的状态,它将和旧的状态进行合并。
如何与TS一起使用
毕竟现在没有人用js开发了吧,看看zustand官方怎么使用的。
使用ts以后,就必须使用create来代替creat了。
为什么要给create 定义状态?它自己不能推断出状态吗?
从上面我们可以看出x最开始是 unknow 类型,后被 interface X 替代
在没有给泛型赋值之前,泛型T是unknow类型。
或者,你可以使用combine ,它能推断出store的类型,你就不用自己给它赋类型了。
至于为什么,‘’-``😩单词都认识,but,解释的太抽象了,看不透本质,谁看懂了,告诉我一下,求求。
如何使用中间件
不需要做什么特别的事情就可以使用中间件了。
嗯?这么容易 ?
哦,使用中间件的时候需要在create里面立刻执行
。。。没听懂???
那我再解释一遍:就是把creat由普通函数---->立即执行函数,立刻执行中间件,使内容承上启下。
嗯,也可以把上面的方法,抽出来,优化一下。
注意:
此外,我们建议尽可能在最外层使用 devtools 中间件。
例如,当您将其与 immer 一起使用作为中间件时,它应该是 devtools(immer(…)) 而不是 immer(devtools(…))。这是因为 devtools 会改变 setState 并在其上添加一个类型参数,如果其他中间件(如 immer)也在 devtools 之前改变 setState,则该参数可能会丢失。因此,在最后使用 devtools 可确保没有中间件在它之前改变 setState。
Slice(TS) 分片
总不能把所有的数据都写在一个文件里吧,那得多邋遢呀
const rootState=create((set,get)=>({bookList: [{ name: '当怪兽来敲门' }],addBook: (book: BookState) => set((state) => {return { bookList: [...state.bookList, book] }}),prizeList: [{ name: '常青藤文学奖' }],
})
创建切片,也就是说把属性按类别分模块
//把属性按模块分开
//值时对象
export const createBookSlice= (set, get) => ({bookList: [{ name: '当怪兽来敲门' }],addBook: (book: BookState) => set((state) => {return { bookList: [...state.bookList, book] }})
})
//值是对象
export const createPrizeSlice = (set, get) => ({prizeList: [{ name: '常青藤文学奖' }],
})
//合并到根状态
const rootState=create((set,get)=>{return {...createBookSlice(set,get),...createPrizeSlice(set,get)}
}
因为最终都整合到rootState中了,取切片的方法时,从rootState中取
例如:const { bookList }=rootState
使用TS写一个未使用中间件的demo
StateCreator<MyState, [], [], MySlice>
使用中间件时TS写法
import { devtools, persist } from 'zustand/middleware'export const useRootStore = create<BookSlice & PrizeSlice,[["zustand/devtools", never], ["zustand/persist", unknown]]
>(devtools(persist((...a) => ({...createBookSlice(...a),...createPrizeSlice(...a),}),{ name: `save all data to localStorage,this is the data's key` },),))
这个中间件干嘛的诶?哦,原来是把数据缓存到本地诶
上面,是把所有的数据都存入localStorage中了,如果我不想全部缓存呢?继续往下看
Persisting store data
Persist 中间件可让您将 Zustand 状态存储在存储中(例如 localStorage、AsyncStorage、IndexedDB 等),从而持久保存其数据。
请注意,此中间件确实支持同步存储(例如 localStorage)和异步存储(例如 AsyncStorage),但使用异步存储确实会带来成本。
看看Persist的属性:
- name:作为storage中数据的key
- storage:默认是localStorage
把你想要存储到localStorage中的数据,赋值给partialize属性
属性很多:https://zustand.docs.pmnd.rs/integrations/persisting-store-data
自己慢慢看吧
可能我说的不太好,基本上全是贴的官网的截图,哈哈哈,纯属我个人习惯,总觉着不从官网了解,心里不踏实。
如果你有更好的学习资料,希望不吝分享@_@