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 ...
解决方案
问题根源
- React Router的
state存储在内存中,刷新页面后会被清空,所以刷新ChildPage时state?.details会变成undefined,后续访问data.color就触发了报错。 - 当前localStorage用法存在逻辑错误:
- 第一个
useEffect依赖data,但初始化时data可能是undefined,直接访问data.id会报错; - 第二个
useEffect是空依赖,执行时data还是初始的undefined,同样会因data.id报错。
- 第一个
修复步骤
方案1:通过URL参数传递ID(最可靠)
因为刷新页面后state会丢失,最稳妥的做法是把数据ID放在URL中,刷新时通过ID重新请求数据或从localStorage读取:
- 修改Card.jsx的Link,将ID加入路径:
<Link to={`/establishments/details/${details.id}`}> <Button>Details</Button> </Link>
- 配置路由时添加参数:
<Route path="/establishments/details/:id" element={<ChildPage />} />
- 在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
相关产品推荐
相关产品推荐

