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

React-query结合react-router-dom路由跳转页面空白问题求助

问题描述

使用react-router-dom进行页面跳转时,React-query出现异常返回undefined,具体场景与表现:

  • 存在两个路由:Home 和 List
  • 在Home组件中通过navigate(/list/${list.id})跳转到List页面
  • 问题现象:
    1. 跳转至List页面时页面空白,刷新后可正常加载
    2. 刷新List页面后返回Home,Home页面空白并报错:Cannot read properties of undefined (reading 'length')

相关代码

Home组件代码

const lists = useQuery(["lists"], api.fetchLists);
...
{lists.isLoading && (
   <React.Fragment>
      <Skeleton />
   </React.Fragment>
)}

...
{isEmpty()}

isEmpty()函数代码

if (lists.data) {
      return lists.data.lists.length ? (
            {lists.data.lists?.map((list) => (

List组件代码

const { listId } = useParams();
const list = useQuery(["lists"], () => api.fetchList(listId));
...
{list.isLoading ? (
        <Card style={{ padding: 30 }}>
          <div>
            <Skeleton />
          </div>
        </Card>
      ) : (
        {list.data}
      )}
原因分析
  1. 缓存Key冲突:Home和List组件的useQuery使用了完全相同的缓存Key["lists"]。跳转List页面时,React-query会用api.fetchList返回的单个列表数据(结构为单个对象,无lists数组字段)覆盖原有缓存。当返回Home时,lists.data已经被替换成单个对象,此时读取lists.data.lists就会得到undefined,进而触发读取length的报错。
  2. 跳转时缓存更新导致渲染异常:跳转List页面时,新请求会更新缓存,但List组件渲染时缓存尚未完成更新,此时缓存中还是Home的数组数据或处于更新中的状态,导致页面空白;刷新List页面时,缓存重新初始化,请求的是单个列表数据,缓存内容匹配组件需求,因此显示正常。
解决方案

1. 给useQuery设置唯一缓存Key

修改List组件的缓存Key,加入listId做区分,彻底避免与Home的缓存冲突:

const { listId } = useParams();
// 缓存Key改为["list", listId],与Home的["lists"]完全区分
const list = useQuery(["list", listId], () => api.fetchList(listId));

2. 完善数据校验与状态处理

  • 优化Home组件的isEmpty()函数,增加多层空值校验,避免读取undefined属性:
function isEmpty() {
  // 用可选链确保每一层存在后再读取length
  if (lists.data?.lists?.length) {
    return lists.data.lists.map((list) => (
      // 你的列表项渲染逻辑
    ));
  }
  // 数据为空时返回空状态提示
  return <div>暂无数据</div>;
}
  • 补充Home组件的错误状态处理,避免请求失败时出现报错:
{lists.isError && <div>加载失败,请重试</div>}
{lists.isLoading && (
   <React.Fragment>
      <Skeleton />
   </React.Fragment>
)}
{!lists.isLoading && !lists.isError && isEmpty()}

3. 优化List组件渲染逻辑

补充错误状态处理,同时避免直接渲染原始的list.data(需根据数据结构渲染具体字段):

{list.isLoading ? (
  <Card style={{ padding: 30 }}>
    <div>
      <Skeleton />
    </div>
  </Card>
) : list.isError ? (
  <div>列表加载失败</div>
) : (
  <div>
    {/* 根据实际数据结构渲染,比如list.data.title、list.data.content等 */}
    {list.data.title}
  </div>
)}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 23:06:27