zustand subscribeWithSelector 使用
zustand subscribeWithSelector 使用
Zustand 提供了一个名为 subscribeWithSelector
的高级功能,允许你在订阅状态时使用一个选择器函数(selector function),类似于 Redux 的 reselect
。选择器函数能够更高效地追踪和计算仅关心的部分状态,减少不必要的渲染。
下面是如何使用 subscribeWithSelector
的示例:
首先,确保你已经在项目中安装了 zustand
并创建了一个 store:
import create from 'zustand';
const useCatStore = create(set => ({
cats: [],
addCat: (newCat) => set(state => ({ cats: [...state.cats, newCat] })),
removeCat: (id) => set(state => ({ cats: state.cats.filter(cat => cat.id !== id) })),
}));
然后,你可以创建一个组件并使用 subscribeWithSelector
:
import { subscribeWithSelector } from 'zustand';
function CatList() {
const selectedCats = subscribeWithSelector(useCatStore, (state) => {
// 在这里编写你的选择器函数,它会根据 store 的状态返回你关心的数据
return state.cats.filter(cat => cat.type === 'big');
});
// 当 `selectedCats` 改变时,组件将重新渲染
// 此处 `selectedCats` 是筛选出的大猫列表
return (
<ul>
{selectedCats.map(cat => (
<li key={cat.id}>{cat.name}</li>
))}
</ul>
);
}
在这个例子中,subscribeWithSelector
接收两个参数:
store
:这是你想要订阅的 zustand store,通常是一个返回 store 的 hook,如useCatStore
。selector
:这是一个函数,它接收整个 store 的状态作为参数,并返回你关心的那一部分状态。
每次 store 的状态发生改变时,selector
会被重新执行,只有当返回值与上一次执行的结果不同时,组件才会重新渲染。这样可以帮助提高大型应用中的性能。
subscribe 订阅
useEffect(() => {
// const unsub = useFoodStore.subscribe((state, prevState) => {
// if (prevState.fish <= 5 && state.fish > 5) {
// setBgColor("lightgreen");
// } else if (prevState.fish > 5 && state.fish <= 5) {
// setBgColor("lightpink");
// }
// });
const unsub = useFoodStore.subscribe(
(state) => state.fish,
(fish, prevFish) => {
// if (fish == prevFish) {
// if (fish <= 5) {
// setBgColor("lightpink");
// } else {
// setBgColor("lightgreen");
// }
// }
if (prevFish <= 5 && fish > 5) {
setBgColor("lightgreen");
} else if (prevFish > 5 && fish <= 5) {
setBgColor("lightpink");
}
},
{
equalityFn: shallow,
fireImmediately: true,
}
);
return unsub;
}, []);
这段代码是使用 React Hooks(结合 Zustand 库)监听状态变化并据此更新组件样式背景色的示例。下面是详细的解释:
-
useEffect
是 React 的内置 Hook,用于处理副作用操作,如订阅事件、定时任务、DOM 更新等。在这个例子中,useEffect
的第二个参数为空数组[]
,意味着这个副作用仅在组件挂载时执行一次。 -
useFoodStore.subscribe
是来自 Zustand 库的方法,用于订阅状态 store 的变化。当 store 中的状态(state)发生变化时,提供的回调函数会被执行。const unsub = useFoodStore.subscribe( (state) => state.fish, (fish, prevFish) => {...} // 其他配置项 ); ``` 第一个参数是选择器函数,它返回 store 中我们需要关注的特定部分(这里是 `state.fish`,鱼的数量)。 第二个参数是订阅的回调函数,它接收两个参数:当前的鱼的数量 `fish` 和前一个鱼的数量 `prevFish`。当 `fish` 的值发生变化时,这个回调函数会被调用。 回调函数内的逻辑是根据鱼的数量变化来切换背景颜色。当鱼的数量从少于等于5变为多于5时,背景色设置为 "lightgreen" ;反之,当鱼的数量从多于5变为少于等于5时,背景色设置为 "lightpink"。
-
equalityFn: shallow
表示在比较新旧状态时使用浅比较(shallow equality check),即只有当引用地址改变时才认为状态发生了变化。 -
fireImmediately: true
表示订阅后立即执行一次回调函数,无论状态是否已经改变。 -
最后,
useEffect
的返回函数unsub
是一个取消订阅的方法,当组件卸载时会自动执行,以防止内存泄漏,确保不再接收无效的状态更新通知。
总结:这段代码在组件挂载时订阅 useFoodStore
中的 fish
状态变化,根据鱼的数量变化动态更改组件的背景色,并在组件卸载时清理订阅。