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 接收两个参数:

  1. store:这是你想要订阅的 zustand store,通常是一个返回 store 的 hook,如 useCatStore
  2. 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 库)监听状态变化并据此更新组件样式背景色的示例。下面是详细的解释:

  1. useEffect 是 React 的内置 Hook,用于处理副作用操作,如订阅事件、定时任务、DOM 更新等。在这个例子中,useEffect
    的第二个参数为空数组 [],意味着这个副作用仅在组件挂载时执行一次。

  2. 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"。
    
    
  3. equalityFn: shallow 表示在比较新旧状态时使用浅比较(shallow equality check),即只有当引用地址改变时才认为状态发生了变化

  4. fireImmediately: true 表示订阅后立即执行一次回调函数,无论状态是否已经改变。

  5. 最后,useEffect 的返回函数 unsub 是一个取消订阅的方法,当组件卸载时会自动执行,以防止内存泄漏,确保不再接收无效的状态更新通知。

总结:这段代码在组件挂载时订阅 useFoodStore 中的 fish 状态变化,根据鱼的数量变化动态更改组件的背景色,并在组件卸载时清理订阅。

posted @ 2024-03-24 00:11  龙陌  阅读(1380)  评论(0)    收藏  举报