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

react-router-dom刷新子页面时state返回TypeError,求解决方法

问题描述

我是react-router-dom新手,在ParentPage.jsx中调用Data方法获取数据,通过Card.jsx映射生成卡片。在Card.jsx中使用<Link/>组件将数据通过state传递到ChildPage,跳转时功能正常,但刷新子页面会返回错误TypeError: Cannot read properties of undefined。我尝试将数据存储到localStorage中,仍出现相同错误,希望能得到帮助。

错误截图

错误截图

代码片段

ParentPage.jsx

const [establishment, setEstablishment] = useState([]);
const Data = () => {
  ...
};

const cards = useMemo(() => {
  return establishment.map((establishment) => (
      <Card establishment={establishment} />
  ));
});

...
    {cards}
...

Card.jsx

const [details] = useState(establishment);
return (
  <>
    <text>{details.name}</text>
    <Link
      to={{
        pathname: "/establishments/details",
        state: { details },
      }}
    >
      <Button>
        Details
      </Button>
    </Link>
  </>
);

ChildPage.jsx

const {state} = useLocation();
const [data, setData] = useState(state?.details);

useEffect(() => {
  window.localStorage.setItem(data.id, JSON.stringify(data));
}, [data]);

useEffect(() => {
  const updatedData = window.localStorage.getItem(data.id);
  if (updatedData !== null) setData(JSON.parse(updatedData));
}, []);

...
  ...data.color
...
解决方案

问题根源

  1. React Router的state存储在内存中,刷新页面后会被清空,所以刷新ChildPage时state?.details会变成undefined,后续访问data.color就触发了报错。
  2. 当前localStorage用法存在逻辑错误:
    • 第一个useEffect依赖data,但初始化时data可能是undefined,直接访问data.id会报错;
    • 第二个useEffect是空依赖,执行时data还是初始的undefined,同样会因data.id报错。

修复步骤

方案1:通过URL参数传递ID(最可靠)

因为刷新页面后state会丢失,最稳妥的做法是把数据ID放在URL中,刷新时通过ID重新请求数据或从localStorage读取:

  1. 修改Card.jsx的Link,将ID加入路径:
<Link to={`/establishments/details/${details.id}`}>
  <Button>Details</Button>
</Link>
  1. 配置路由时添加参数:
<Route path="/establishments/details/:id" element={<ChildPage />} />
  1. 在ChildPage中获取ID并处理数据:
import { useParams, useLocation } from 'react-router-dom';

const ChildPage = () => {
  const { id } = useParams();
  const { state } = useLocation();
  // 优先用state的data,没有则从localStorage读取,最后兜底为空对象
  const [data, setData] = useState(state?.details || JSON.parse(localStorage.getItem(id)) || {});

  // 存储数据到localStorage,先判断data是否有效
  useEffect(() => {
    if (data?.id) {
      localStorage.setItem(data.id, JSON.stringify(data));
    }
  }, [data]);

  // 渲染前先判断数据是否存在,避免报错
  if (!data?.color) {
    return <div>加载中...</div>;
  }

  return (
    <div>{data.color}</div>
    // 其他渲染内容
  );
};

方案2:仅修复localStorage用法(适合临时场景)

如果不想修改路由结构,需要确保访问data属性前先判断是否存在:

const {state} = useLocation();
// 给data初始值为空对象,避免undefined
const [data, setData] = useState(state?.details || {});

useEffect(() => {
  // 先判断data.id存在再执行存储
  if (data.id) {
    window.localStorage.setItem(data.id, JSON.stringify(data));
  }
}, [data]);

useEffect(() => {
  // 先获取有效ID,优先用state里的,没有则用默认值(不推荐多个数据场景)
  const targetId = state?.details?.id || 'temp_establishment';
  const updatedData = window.localStorage.getItem(targetId);
  if (updatedData !== null) {
    setData(JSON.parse(updatedData));
  }
}, []);

// 渲染时用可选链访问属性,避免报错
return (
  <div>{data?.color}</div>
);

关键提醒

  • 永远不要依赖React Router的state存储关键数据,刷新后会丢失;
  • 访问嵌套属性前一定要用可选链操作符?.,或者先判断数据是否存在;
  • 涉及页面刷新的数据,优先用「URL参数+后端请求/localStorage」的组合。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 17:15:34