You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Zustand中统一更新combinedData,避免多组件重复使用useEffect?

问题描述

我创建了如下Zustand store用于生成派生数据:

import { create } from "zustand";
import myDataStore from "./myDataStore";

type State = {
    combinedData: any;
    combineData: () => void;
};

const myCombinedData = create<State>((set) => ({
    combinedData: [],
    combineData: () =>
        set(() => {
            const myData = myDataStore.getState().data;

            const newCombinedData = myData.df.map((item, index) => {
                return { ...item, ...myData.df_other[index] };
            });
            return { combinedData: newCombinedData };
        }),
}));

export default myCombinedData;

这个store依赖另一个存储数据的Zustand store(myDataStore)生成派生数据combinedData。目前在组件中我需要这样调用:

const myData = myDataStore((state) => state.data);
const { combinedData, combineData } = myCombinedData();

useEffect(() => {
    combineData();
}, [myData]);

现在的问题是,多个组件都需要使用combinedData,每个组件都写这段useEffect太冗余,想知道有没有办法在单个位置实现每当myData变化时自动更新combinedData?

解决方案

方法1:在myCombinedData内部订阅myDataStore的变化

直接在myCombinedData内部监听myDataStore的更新,一旦data变化就自动重新计算combinedData,把所有逻辑封装在store内部,组件无需额外处理。

修改后的myCombinedData代码:

import { create } from "zustand";
import myDataStore from "./myDataStore";

type State = {
    combinedData: any;
};

// 抽离计算逻辑,复用性更强
const calculateCombinedData = (data: typeof myDataStore.getState().data) => {
    return data.df.map((item, index) => ({
        ...item,
        ...data.df_other[index]
    }));
};

const myCombinedData = create<State>((set) => {
    // 初始化组合数据
    const initialData = calculateCombinedData(myDataStore.getState().data);
    
    // 订阅myDataStore的data字段变化
    const unsubscribe = myDataStore.subscribe(
        (state) => state.data,
        (newData) => {
            set({ combinedData: calculateCombinedData(newData) });
        },
        { fireImmediately: true } // 确保初始化时触发一次计算
    );

    // store销毁时自动取消订阅,避免内存泄漏
    return {
        combinedData: initialData,
        // 可选:如果需要手动触发更新,可保留该方法
        // combineData: () => set({ combinedData: calculateCombinedData(myDataStore.getState().data) })
    };
});

export default myCombinedData;

组件中直接获取数据即可:

const { combinedData } = myCombinedData();

方法2:封装自定义hook复用逻辑

如果不想改动原有store,可以封装一个自定义hook,把监听和更新逻辑集中在hook里,所有组件直接调用该hook:

import { useEffect } from "react";
import myDataStore from "./myDataStore";
import myCombinedData from "./myCombinedData";

export const useCombinedData = () => {
    const myData = myDataStore((state) => state.data);
    const { combinedData, combineData } = myCombinedData();

    useEffect(() => {
        combineData();
    }, [myData, combineData]);

    return combinedData;
};

组件中使用方式:

const combinedData = useCombinedData();

内容的提问来源于stack exchange,提问作者Denver Dang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 14:52:17