zustand如何进行监听属性的变化?

zustand如何进行监听属性的变化?
比如我有:Slice如下:

export interface SectionSlice {
  Sections: Section[],
  selectedSection: Section | undefined,
  isLoading: boolean,

  selectSection: (SectionID: number) => void,
  fetchSections: () => Promise<void>,
  addSection: (Section:Section) => Promise<void>,
  updateSection: (Section:Section) => Promise<void>,
  deleteSection: (id: number) => Promise<void>,

  SectionMods: SectionMod[],
  selectedSectionMod: SectionMod | undefined,
  selectSectionMod: (SectionModId: number) => Promise<void>,
  fetchSectionMods: (SectionId: number) => Promise<void>,
}

//type SliceType = StateCreator<SectionSlice, [], [], SectionSlice>

export const createSectionSlice: StateCreator<SectionSlice> = (set, get) => ({

  // 1.状态
  Sections: [] as Section[],
  selectedSection: undefined as Section | undefined,

  SectionMods: [] as SectionMod[],
  selectedSectionMod: undefined as SectionMod | undefined,

  // 2.操作状态的actions

  isLoading: false, // 是否正在操作
  fetchSections: async() => {
    try {
      set({ isLoading: true })
      const Sections: Section[] = await getSections()

      set({ Sections: Sections })
    } catch (error) {

    } finally {
      set({ isLoading: false })
    }
  },

  // 选择项目
  selectSection: (SectionID: number) => {

    // 基于SectionID获取Section
    const { Sections } = get()
    const filteredSection = (Sections as Section[]).filter((Section: Section) => Section.id === SectionID);



    set({ selectedSection: filteredSection[0] })
  },

  addSection: async(Section:Section) => {
    try {
      set({ isLoading: true })
      await addSection(Section)
    } catch (error) {

    } finally {
      const { fetchSections } = get(); // 通过get获取当前状态里的fetchSections方法
      fetchSections()
      set({ isLoading: false })
    }
  },

  updateSection: async(Section: Section) => {
    try {
      set({ isLoading: true })
      await updateSection(Section)
    } catch (error) {

    } finally {
      const { fetchSections } = get(); // 通过get获取当前状态里的fetchSections方法
      fetchSections()
      set({ isLoading: false })
    }
  },

  deleteSection: async(id: number) => {
    try {
      set({ isLoading: true })
      await deleteSection(id)
    } catch (error) {

    } finally {
      const { fetchSections } = get(); // 通过get获取当前状态里的fetchSections方法
      fetchSections()
      set({ isLoading: false })
    }
  },

  selectSectionMod: async(SectionModId: number) => {

    // 基于SectionID获取Section
    const { SectionMods } = get()
    const filteredSectionMod = (SectionMods as SectionMod[]).filter((SectionMod: SectionMod) => SectionMod.id === SectionModId);

    set({selectedSectionMod: filteredSectionMod[0]})
  },

  fetchSectionMods: async(SectionId: number) => {

    try {
      set({ isLoading: true })

      const SectionMods: SectionMod[] = await getSectionMods(SectionId)
      set({ SectionMods: SectionMods })

      const { selectedSectionMod } = get()
      if( !selectedSectionMod ) {

        const mainSectionMods: SectionMod[] = SectionMods.filter((SectionMod) => SectionMod.isMain === true);
        set({ selectedSectionMod:  mainSectionMods[0]})
      }

    } catch (error) {

    } finally {
      set({ isLoading: false })
    }

  },

})

我想要在Store内(可以是Slice中)中监听:selectedSection 变化(比如:我想要知道selectedSection改变之后,立即就触发方法,在方法里面操作),在监听的事件里面在做其他的操作。

阅读 1.1k
avatarAI BotBETA

在 Zustand 中,你可以使用 subscribe 方法来监听状态的变化。虽然 Zustand 没有直接的“监听器”或“观察者”模式,但你可以通过订阅整个状态树并在回调函数中检查你感兴趣的状态是否发生变化来实现类似的功能。

下面是一个如何在 Zustand 中监听 selectedSection 变化的示例:

### 监听 `selectedSection` 变化

你可以在你的组件或任何需要监听状态变化的地方使用 `subscribe` 方法。以下是一个示例,展示了如何在 `createSectionSlice` 之外订阅 `selectedSection` 的变化:

import create, { State } from 'zustand';
import { createSectionSlice } from './path-to-your-slice'; // 假设你的 slice 文件在这里

// 创建 store
const useStore = create(set => ({
...createSectionSlice(set, get), // 展开你的 slice
// 你可以在这里添加其他状态或方法
}));

// 使用 subscribe 方法监听状态变化
const unsubscribe = useStore.subscribe((state: State<typeof useStore>, prevState: State<typeof useStore>) => {
// 检查 selectedSection 是否变化
if (state.selectedSection !== prevState.selectedSection) {

console.log('selectedSection has changed:', state.selectedSection);

// 在这里执行你想要的操作
// 例如:
handleSelectedSectionChange(state.selectedSection);

}
});

// 假设这是你的处理函数
function handleSelectedSectionChange(selectedSection: Section | undefined) {
// 在这里处理 selectedSection 的变化
console.log('Handling selectedSection change:', selectedSection);
// ... 你的逻辑
}

// 在组件中使用 store
import React, { useEffect } from 'react';
import { useStore } from './path-to-your-store'; // 假设你的 store 文件在这里

function MyComponent() {
const store = useStore();

useEffect(() => {

// 可以在这里进行一些组件挂载时的逻辑
// ...

// 清理函数,用于在组件卸载时取消订阅
return () => {
  unsubscribe();
};

}, []); // 空依赖数组表示这个 effect 只在组件挂载和卸载时运行一次

return (

// 你的组件 JSX

);
}


### 解释

1. **创建 Store**:使用 `create` 方法创建你的 store,并将 `createSectionSlice` 展开到 store 中。
2. **订阅状态变化**:使用 `subscribe` 方法订阅整个状态树的变化。回调函数会接收当前状态和上一个状态。
3. **检查 `selectedSection` 变化**:在回调函数中,检查 `selectedSection` 是否发生了变化。如果变化了,执行相应的处理逻辑。
4. **在组件中使用 Store**:在你的 React 组件中使用 `useStore` 钩子来获取 store 的状态,并在组件卸载时取消订阅(使用 `unsubscribe` 函数)。

注意:在组件中使用 `subscribe` 时,通常会在 `useEffect` 中进行订阅,并在返回的清理函数中取消订阅,以避免内存泄漏。
1 个回答
import { create } from 'zustand'
import { subscribeWithSelector } from 'zustand/middleware'

//用 subscribeWithSelector
const useSectionStore = create(
  subscribeWithSelector(
    (set, get) => createSectionSlice(set, get)
  )
)

useSectionStore.subscribe(
  (state) => state.selectedSection,
  (selectedSection, previousSelectedSection) => {
    
    console.log('selectedSection changed:', selectedSection)
    console.log('previous value:', previousSelectedSection)
    
    // 比如自动获取 Section 的 Mods
    if (selectedSection) {
      useSectionStore.getState().fetchSectionMods(selectedSection.id)
    }
  }
)

用的时候:

const unsubscribe = useSectionStore.subscribe(
  (state) => state.selectedSection,
  (selectedSection, previousSelectedSection) => {
    // 处理
  },
  {
    equalityFn: shallow // 自定义比较函数
  }
)

useEffect(() => {
  const unsubscribe = useSectionStore.subscribe(
    (state) => state.selectedSection,
    (selectedSection) => {
      // 处理
    }
  )
  
  return () => unsubscribe()
}, [])
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏