自定义hook中变量更新时useEffect未触发的问题排查
问题原因与解决方案
核心问题:自定义Hook的状态是组件独立的
你遇到的问题根源在于:每个组件调用useHiddenStatistics时,都会生成完全独立的状态副本。也就是说,调用moveTohiddenStatistics的文件,修改的是它自身组件内部的hiddenStatistics状态;而文件X里的hiddenStatistics是另一个完全独立的数组,根本没被修改过,所以依赖它的useEffect自然不会触发。
解决方法:用Context共享状态
要让多个组件共享同一状态,需要把状态放到React Context中,让所有需要的组件都从同一个Context里获取状态和修改方法。
步骤1:创建Context文件
新建HiddenStatisticsContext.tsx文件:
import { createContext, useContext, useState, ReactNode } from 'react'; // 定义Context类型 type HiddenStatisticsContextType = { hiddenStatistics: string[]; moveTohiddenStatistics: (item: string) => void; }; // 创建Context const HiddenStatisticsContext = createContext<HiddenStatisticsContextType | null>(null); // 创建Provider组件,负责管理共享状态 export const HiddenStatisticsProvider = ({ children }: { children: ReactNode }) => { const [hiddenStatistics, setHiddenStatistics] = useState<string[]>(["a", "b"]); const moveTohiddenStatistics = (item: string) => { setHiddenStatistics((prev) => [...prev, item]); }; return ( <HiddenStatisticsContext.Provider value={{ hiddenStatistics, moveTohiddenStatistics }}> {children} </HiddenStatisticsContext.Provider> ); }; // 封装获取Context的自定义Hook export const useHiddenStatistics = () => { const context = useContext(HiddenStatisticsContext); if (!context) { throw new Error("useHiddenStatistics必须在HiddenStatisticsProvider内部使用"); } return context; };
步骤2:用Provider包裹根组件
在应用根组件(比如App.tsx)中,用HiddenStatisticsProvider包裹所有需要共享状态的组件:
import { HiddenStatisticsProvider } from './HiddenStatisticsContext'; function App() { return ( <HiddenStatisticsProvider> {/* 这里放入你的页面组件,包括文件X和调用moveTohiddenStatistics的组件 */} <FileX /> <OtherComponent /> </HiddenStatisticsProvider> ); }
步骤3:组件中使用共享状态
现在文件X和另一个组件都能获取到同一状态:
文件X的代码无需大幅修改,现在它的hiddenStatistics会和其他组件同步:
import { useHiddenStatistics } from './HiddenStatisticsContext'; import { useEffect } from 'react'; const FileX = () => { const { hiddenStatistics } = useHiddenStatistics(); useEffect(() => { console.log("set hidden statistics", hiddenStatistics); }, [hiddenStatistics]); return <div>当前隐藏统计项:{hiddenStatistics.join(", ")}</div>; };
调用修改方法的组件:
import { useHiddenStatistics } from './HiddenStatisticsContext'; const OtherComponent = () => { const { moveTohiddenStatistics } = useHiddenStatistics(); return ( <button onClick={() => moveTohiddenStatistics("c")}> 添加统计项 </button> ); };
这样修改后,当点击按钮调用moveTohiddenStatistics时,所有组件共享的hiddenStatistics会更新,文件X里的useEffect也会随之触发。
内容的提问来源于stack exchange,提问作者Jan D.M.
相关产品推荐
相关产品推荐

