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

React中history.push配合useLocation出现读取data为undefined错误如何解决

问题原因
  • 报错本质是直接访问了可能为undefined的对象属性,核心触发场景有两个:
    1. 若组件2使用了路由缓存、或处于嵌套路由的父级位置未被正常卸载,跳转其他路由后useLocation会自动更新为新路由的location对象,新路由的state未携带data字段,此时组件2因任何原因触发重渲染就会抛出错误
    2. 即便是正常场景,用户直接在地址栏输入/chat路由访问组件2时,没有经过组件1的history.push携带参数,location.state本身就是undefined,也会触发同样报错
现有问题修复方案

给location.state的取值加兜底逻辑即可,推荐使用可选链+空值合并运算符做兼容:

// 组件2取值逻辑修改
const location = useLocation()
const data = location.state?.data ?? {}

渲染部分直接用data取值即可:

<IonCardSubtitle>{data.contactPerson}</IonCardSubtitle>
<IonCardSubtitle>{data.email}</IonCardSubtitle>
<IonCardTitle>{data.name}</IonCardTitle>
不依赖location hook的编程式路由传参方案

1. URL查询参数传参

将参数拼接在路由查询串中,不需要依赖React路由的hook,直接通过浏览器原生API读取:

// 组件1跳转逻辑
history.push({
  pathname: '/chat',
  // 拼接查询参数,复杂参数可以先序列化
  search: new URLSearchParams({
    contactPerson: location.state.data.contactPerson,
    email: location.state.data.email,
    name: location.state.data.name
  }).toString()
})
// 组件2读取逻辑,不需要useLocation
const searchParams = new URLSearchParams(window.location.search)
const contactPerson = searchParams.get('contactPerson')
const email = searchParams.get('email')
const name = searchParams.get('name')

特点:参数刷新不丢失,实现简单;缺点是参数暴露在地址栏,无法传递复杂引用类型数据。

2. 全局状态存储传参

用Context、Redux、Zustand等全局状态管理方案存储传递的参数,跳转前写入状态,目标组件读取即可:

// 示例:基于原生Context实现
// 全局Context定义
const RouteParamContext = createContext(null)

// 根组件注入
function App() {
  const [routeParams, setRouteParams] = useState({})
  return (
    <RouteParamContext.Provider value={{routeParams, setRouteParams}}>
      {/* 路由组件 */}
    </RouteParamContext.Provider>
  )
}
// 组件1跳转前写入
const { setRouteParams } = useContext(RouteParamContext)
setRouteParams({ chat: location.state.data })
history.push('/chat')
// 组件2读取,不需要useLocation
const { routeParams } = useContext(RouteParamContext)
const data = routeParams.chat ?? {}

特点:可传递任意类型数据,不会暴露在地址栏;缺点是刷新页面数据会丢失,需要额外做持久化。

3. 浏览器存储传参

用sessionStorage或localStorage存储参数,跳转前写入,目标组件读取后可选择删除:

// 组件1跳转前写入
sessionStorage.setItem('chatParams', JSON.stringify(location.state.data))
history.push('/chat')
// 组件2读取,不需要useLocation
const data = JSON.parse(sessionStorage.getItem('chatParams') ?? '{}')
// 组件卸载时清理参数
useEffect(() => {
  return () => sessionStorage.removeItem('chatParams')
}, [])

特点:实现无依赖,刷新页面参数不丢失;缺点是只能存储可序列化的数据,单条存储容量有限制。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 07:24:04