使用RTK-Query设置React Context值遇问题:数据未加载Context已渲染
问题分析与修复方案
你的代码存在几个关键问题,导致数据未加载完成时Context就完成渲染:
- RTK Query Hooks调用位置错误:
useFetchMyQuery()作为React Hook,必须直接在组件顶层调用,不能放在useEffect内部——这违反了React Hooks的规则,同时会导致你无法在组件顶层获取isFetching、data等状态,加载判断逻辑完全失效。 - 冗余的
useState:RTK Query已经内置了数据缓存与状态管理,不需要额外用useState来存储data,额外的状态会导致数据不同步,且初始状态未对齐Context默认值。 - 依赖数组错误:
useEffect的依赖数组中引用的data、isFetching等变量是在effect内部声明的,组件顶层根本不存在这些变量,这会导致lint报错,且effect逻辑完全无法按预期触发。
修正后的代码
export const defaultContext = { header: {}, }; export const MyContext = React.createContext(defaultContext); export default function Page({ className, children, loadingText }) { // 直接在组件顶层调用RTK Query的Hook const { data, isFetching, isError } = useFetchMyQuery(); // 加载状态判断:此时isFetching是实时的RTK Query状态 if (isFetching) { return <Loader message={loadingText} />; } // 使用RTK Query返回的data作为Context值,若data为undefined则用默认值兜底 const contextValue = data ?? defaultContext; return ( <DndProvider backend={HTML5Backend}> <MyContext.Provider value={contextValue}> <div className={`${styles.page} ${className}`}> <div className={styles.leftSide} /> <div className={styles.rightSide} /> {children} </div> </MyContext.Provider> </DndProvider> ); }
关键修改说明
- 将RTK Query Hook移到组件顶层:这样能直接获取到
isFetching、data等实时状态,加载判断逻辑可以正常生效,确保数据加载完成后才渲染Context Provider和子组件。 - 移除冗余的
useState与useEffect:直接使用RTK Query返回的data,避免状态冗余和不同步问题;同时用??运算符兜底,确保Context值始终符合defaultContext的结构,避免子组件消费Context时出现属性undefined的问题。 - 修正加载判断逻辑:现在
isFetching是RTK Query提供的真实加载状态,会在数据请求过程中保持true,直到数据加载完成,此时才会渲染后续的Context和页面内容。
内容的提问来源于stack exchange,提问作者Aleksandar Andrijevic
相关产品推荐
相关产品推荐

