React中Context更新后如何让组件获取最新值的问题咨询
React中Context更新后组件无法获取新值的解决方案
问题描述
我希望在Context更新时让组件使用其新值,目前从服务器加载应用设置的代码如下:
import { Context, createContext, useEffect, useState } from "react"; export class AppSettings { buildName: string = ''; authority: string = ''; truthPortalApi: string = ''; environment: string = ''; } export const AppSettingsContext: Context<AppSettings> = createContext<AppSettings>(null!) export const AppSettingsProvider: React.FC<{ children: JSX.Element }> = ({ children }) => { const [settings, setSettings] = useState<AppSettings>(new AppSettings()) useEffect(() => { fetch(`${window.location.origin}/settings`) .then(response => response.json()) .then(data => setSettings(data)) }, []); return ( <AppSettingsContext.Provider value={settings}> {children} </AppSettingsContext.Provider> ) }
之后在AuthProvider中使用这些设置的代码如下:
... export const AuthContext: Context<AuthService> = createContext<AuthService>(null!); export const AuthProvider: React.FC<{ children: JSX.Element[] }> = ({ children }) => { let appSettings: AppSettings = useContext<AppSettings>(AppSettingsContext)!; const [authService, setAuthService] = useState<AuthService>(new AuthService(appSettings)); return ( <AuthContext.Provider value={authService}> { children } </AuthContext.Provider> ); } export function useAuth(): AuthService { return useContext(AuthContext); }
但通过let auth: AuthService = useAuth();使用auth的组件仅能拿到初始空值,无法获取加载后的真实值。
问题原因
AuthProvider中的useState仅在组件首次初始化时执行一次,后续appSettings从服务器加载完成并更新Context后,authService状态不会自动重新创建,导致下游组件拿到的始终是初始的空值实例。
解决方案
方案一:使用useEffect监听appSettings变化
通过useEffect监听appSettings的更新,当依赖项变化时重新创建AuthService并更新状态:
export const AuthProvider: React.FC<{ children: JSX.Element[] }> = ({ children }) => { const appSettings = useContext(AppSettingsContext)!; const [authService, setAuthService] = useState<AuthService>(new AuthService(appSettings)); // 当appSettings更新时,重新生成AuthService实例 useEffect(() => { setAuthService(new AuthService(appSettings)); }, [appSettings]); // 依赖数组中加入appSettings,触发更新 return ( <AuthContext.Provider value={authService}> { children } </AuthContext.Provider> ); }
方案二:直接在渲染时创建AuthService(无状态缓存)
如果AuthService的创建成本较低,无需缓存实例,可以直接在组件渲染阶段生成,这样每次appSettings更新都会自动生成新的实例:
export const AuthProvider: React.FC<{ children: JSX.Element[] }> = ({ children }) => { const appSettings = useContext(AppSettingsContext)!; // 每次渲染时根据最新的appSettings创建AuthService const authService = new AuthService(appSettings); return ( <AuthContext.Provider value={authService}> { children } </AuthContext.Provider> ); }
额外优化:处理未加载完成的边界情况
由于AppSettings初始值为空,建议在AuthProvider中先判断关键字段是否加载完成,避免创建无效的AuthService,同时给用户反馈:
export const AuthProvider: React.FC<{ children: JSX.Element[] }> = ({ children }) => { const appSettings = useContext(AppSettingsContext)!; const [authService, setAuthService] = useState<AuthService | null>(null); useEffect(() => { // 确保核心配置字段存在后再创建AuthService if (appSettings.authority && appSettings.truthPortalApi) { setAuthService(new AuthService(appSettings)); } }, [appSettings]); // 未加载完成时显示加载状态 if (!authService) { return <div>应用初始化中...</div>; } return ( <AuthContext.Provider value={authService}> { children } </AuthContext.Provider> ); }
内容的提问来源于stack exchange,提问作者Richard Barraclough
相关产品推荐
相关产品推荐

