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

自定义Hook中useEffect未因其他Hook依赖变更触发问题

问题:自定义Hook状态无法跨组件同步,useEffect不触发

我有一个自定义Hook useProvideAuth,用于管理accessToken状态和更新方法:

export function useProvideAuth() {
    const [accessToken, setAccessToken] = useState<string>(
        "noToken"
    );

    const setAuth = (newToken: string) => {
        // 注:为简化未包含完整逻辑
        setAccessToken(newToken);
    };
    return { accessToken, setAccessToken: setAuth };
};

随后在另一个自定义Hook useMyUserDetails 中使用它,并将accessToken作为useEffect的依赖:

export function useMyUserDetails() {
    const { accessToken } = useProvideAuth();

    useEffect(() => {
        // 执行相关操作
        // 当accessToken变更时,此useEffect从未被调用
    }, [accessToken]);
}

遇到的问题:useMyUserDetails中的useEffect仅在初始时执行一次,accessToken变更时完全不触发。调用setAccessToken的组件内accessToken确实已更新,但useMyUserDetails中的accessToken始终未变化。


原因分析

每个组件或自定义Hook调用useProvideAuth时,都会创建独立的useState状态实例。也就是说,调用setAuth的组件里的accessToken,和useMyUserDetails里的accessToken是两个互不相干的状态,自然无法同步更新。


解决方案:用React Context共享状态

要实现跨组件/Hook的状态同步,需要用React Context来统一管理Auth状态,让所有消费它的组件共享同一个状态实例。

1. 创建Auth Context与Provider

// auth-context.tsx
import { createContext, useContext, useState, ReactNode } from 'react';

// 定义Context的类型
type AuthContextType = {
  accessToken: string;
  setAuth: (newToken: string) => void;
};

// 创建Context,默认值仅用于类型提示
const AuthContext = createContext<AuthContextType | undefined>(undefined);

// 实现Provider组件,统一管理状态
export function AuthProvider({ children }: { children: ReactNode }) {
  const [accessToken, setAccessToken] = useState<string>("noToken");

  const setAuth = (newToken: string) => {
    // 可在此添加完整逻辑(如存入localStorage)
    setAccessToken(newToken);
  };

  return (
    <AuthContext.Provider value={{ accessToken, setAuth }}>
      {children}
    </AuthContext.Provider>
  );
}

// 自定义Hook用于安全消费Context
export function useProvideAuth() {
  const context = useContext(AuthContext);
  if (!context) {
    throw new Error('useProvideAuth必须在AuthProvider内部使用');
  }
  return context;
}

2. 改造useMyUserDetails

现在调用useProvideAuth会拿到共享的全局状态,状态更新时useEffect会正常触发:

export function useMyUserDetails() {
    const { accessToken } = useProvideAuth();

    useEffect(() => {
        console.log('accessToken已更新:', accessToken);
        // 执行你的业务操作
    }, [accessToken]);
}

3. 在根组件中包裹Provider

确保所有需要共享Auth状态的组件都被AuthProvider包裹:

// App.tsx
import { AuthProvider } from './auth-context';
import TokenSetterComponent from './TokenSetterComponent'; // 调用setAuth的组件
import UserDetailsComponent from './UserDetailsComponent'; // 使用useMyUserDetails的组件

function App() {
  return (
    <AuthProvider>
      <TokenSetterComponent />
      <UserDetailsComponent />
    </AuthProvider>
  );
}

export default App;

这样修改后,任何组件调用setAuth更新accessToken时,所有消费useProvideAuth的地方都会同步拿到最新值,对应的useEffect也会触发执行。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 12:35:15