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

