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

React路由页面刷新数据丢失问题排查求助

问题原因与解决方案

核心原因

  1. 异步请求时序与未处理空状态
    刷新页面时,App组件重新挂载,API请求是异步操作,在请求完成前data保持初始空数组状态。ItemList组件直接执行data.filter(...)[0].items,当data为空时,filter返回空数组,取[0]得到undefined,访问undefined.items会抛出错误,导致组件渲染失败,表现为“数据消失”。

  2. 缺失加载状态与数据校验
    ItemList组件未利用传入的isLoading状态做加载判断,也没有对data是否存在、分类是否找到做校验,直接访问深层属性引发报错。

解决方案

1. 修复ItemList组件,增加状态判断与数据校验

修改ItemList组件,在数据未就绪、分类不存在时给出对应提示,避免直接访问undefined属性:

function ItemList({ name, data, isLoading }) {
  // 加载中状态处理
  if (isLoading) {
    return <div>加载中...</div>;
  }

  // 数据为空时的提示
  if (!data || data.length === 0) {
    return <div>暂无数据</div>;
  }

  // 查找对应分类,替代filter+[0]的写法,更直观
  const targetCategory = data.find(
    (el) => name.toLowerCase() === el.name.toLowerCase()
  );

  // 分类不存在时的提示
  if (!targetCategory) {
    return <div>未找到指定分类</div>;
  }

  const items = targetCategory.items;

  return (
    <ul className={styles.itemList}>
      {items.map((el) => (
        <Item item={el} key={el.id} /> {/* 注意:用item的唯一ID作为key,避免使用随机UUID,提升渲染性能 */}
      ))}
    </ul>
  );
}

2. 确保App组件的状态初始值正确

确认data的初始状态为数组,避免类型错误:

const [data, setData] = useState([]);

3. 可选:用Context管理全局数据(优化props传递)

如果项目规模扩大,建议使用React Context封装数据请求与状态管理,避免props层层传递,同时保证刷新页面时数据能在全局共享:

// 创建DataContext.js
import { createContext, useContext, useEffect, useState } from 'react';
import { BASE_URL } from './constants';

const DataContext = createContext();

export function DataProvider({ children }) {
  const [data, setData] = useState([]);
  const [isLoading, setIsLoading] = useState(false);

  useEffect(() => {
    async function fetchData() {
      try {
        setIsLoading(true);
        const res = await fetch(`${BASE_URL}/gahlot1999/fake-api/categories`);
        const fetchedData = await res.json();
        setData(fetchedData);
      } catch {
        alert('加载数据出错');
      } finally {
        setIsLoading(false);
      }
    }
    fetchData();
  }, []);

  return (
    <DataContext.Provider value={{ data, isLoading }}>
      {children}
    </DataContext.Provider>
  );
}

export function useData() {
  return useContext(DataContext);
}

然后在App组件中包裹Provider:

import { DataProvider } from './DataContext';

function App() {
  return (
    <DataProvider>
      <BrowserRouter>
        <Routes>
          <Route path='/' element={<Home />} />
          <Route path='/app' element={<AppLayout />} />
          <Route path='app/:name' element={<Category />} />
        </Routes>
      </BrowserRouter>
    </DataProvider>
  );
}

后续组件直接用useData获取数据,比如Category组件:

import { useData } from './DataContext';

function Category() {
  const { name } = useParams();
  const { data, isLoading } = useData();
  return (
    <div className={styles.container}>
      <SideBar name={name} />
      <ItemList name={name} data={data} isLoading={isLoading} />
    </div>
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 18:03:13