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

如何在useEffect中正确使用React Query数据设置默认工作区?

React Query获取数据后,仅首次渲染设置默认值失败

我想用React Query给组件获取数据,要求仅在组件首次渲染时设置默认值,于是尝试在useEffect里用useQuery返回的数据,但没成功,还出现了报错。

我的代码

Header组件代码

export default function Header() {
.
.
.

    //Here i'm using a custom hook
  const { data: workSpaceArray } = useWorkspacesByUserData(onFetchWorkspaceSuccess, onFetchWorkspaceError);
  
   useEffect(() => {
   const defaultWorkspaceItem = workSpaceArray?.data.info.workspaces.filter(workspace => workspace.name === workSpaceArray?.data.info.default_workspace_id);
   localStorage.removeItem(USER_WORKSPACE);
   localStorage.setItem(USER_WORKSPACE, JSON.stringify(defaultWorkspaceItem[0]));
   setSelectedWorkspaceValue(defaultWorkspaceItem[0].name)
 }, []);
  
  return(
  ...
  );
  
  }

自定义hook代码

import { useQuery, useMutation } from 'react-query'
import { protectedRequest } from '../utils/axios-utils'
import { ResponseHandler } from "./ResponseHandler"

const fetchWorkspacesByUserId = async () => {
    const response = await protectedRequest({ url: '/workspace/load' });
    return ResponseHandler(response);
}

export const useWorkspacesByUserData = (onSuccess, onError) => {
    return useQuery('fetch-workspaces-by-user', fetchWorkspacesByUserId,
        {
            onSuccess,
            onError,
            staleTime: 120000,
        })
}

问题分析

  1. 异步数据时机问题:你的useEffect依赖是空数组,首次渲染时workSpaceArray还未拿到异步请求的返回值,处于undefined状态,后续访问嵌套属性和操作defaultWorkspaceItem[0]会直接抛出Cannot read properties of undefined错误。
  2. 匹配逻辑错误:filter里用workspace.name === default_workspace_id,明显是逻辑错误——工作区名称和ID不可能匹配,这会导致defaultWorkspaceItem为空数组,defaultWorkspaceItem[0]自然不存在。

解决方案

方案一:利用React Query的onSuccess回调(推荐)

既然自定义hook已经支持传入onSuccess,直接在这个回调里处理默认值设置是最合理的:onSuccess会在数据成功获取后触发,结合staleTime配置,数据新鲜时不会重复执行,完美符合“首次渲染设置”的需求。

修改Header组件:

export default function Header() {
  const onFetchWorkspaceSuccess = (data) => {
    // 修正匹配逻辑:用工作区ID和默认ID对比
    const defaultWorkspaceItem = data.info.workspaces.filter(
      workspace => workspace.id === data.info.default_workspace_id
    );
    
    // 先判断匹配结果是否存在,避免报错
    if (defaultWorkspaceItem[0]) {
      localStorage.removeItem(USER_WORKSPACE);
      localStorage.setItem(USER_WORKSPACE, JSON.stringify(defaultWorkspaceItem[0]));
      setSelectedWorkspaceValue(defaultWorkspaceItem[0].name);
    }
  };

  const onFetchWorkspaceError = (error) => {
    console.error('加载工作区失败:', error);
    // 可添加用户提示逻辑
  };

  const { data: workSpaceArray } = useWorkspacesByUserData(onFetchWorkspaceSuccess, onFetchWorkspaceError);
  
  return(
    // ... 组件原有内容
  );
}

方案二:给useEffect添加正确依赖(可选)

如果一定要用useEffect,需要添加workSpaceArray作为依赖,并增加数据存在性判断,同时可以加状态标记避免重复执行:

export default function Header() {
  const { data: workSpaceArray } = useWorkspacesByUserData(onFetchWorkspaceSuccess, onFetchWorkspaceError);
  const [isDefaultSet, setIsDefaultSet] = useState(false);
  
  useEffect(() => {
    // 已设置过默认值,或数据未加载完成时直接返回
    if (isDefaultSet || !workSpaceArray?.data?.info) return;
    
    // 修正匹配逻辑
    const defaultWorkspaceItem = workSpaceArray.data.info.workspaces.filter(
      workspace => workspace.id === workSpaceArray.data.info.default_workspace_id
    );
    
    if (defaultWorkspaceItem[0]) {
      localStorage.removeItem(USER_WORKSPACE);
      localStorage.setItem(USER_WORKSPACE, JSON.stringify(defaultWorkspaceItem[0]));
      setSelectedWorkspaceValue(defaultWorkspaceItem[0].name);
      setIsDefaultSet(true); // 标记已完成设置,避免后续重复执行
    }
  }, [workSpaceArray, isDefaultSet]);
  
  return(
    // ... 组件原有内容
  );
}

关键注意事项

  • 必须修正filter的匹配逻辑,用workspace.id和default_workspace_id对比,否则无法找到目标工作区。
  • 任何时候访问嵌套对象前都要做存在性判断,避免因数据未加载完成导致的报错。

内容的提问来源于stack exchange,提问作者Deshan-Charuka

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 06:35:30