React ES6路由组件访问props报undefined错误排查修复
问题根因
报错由react-router-dom版本差异导致:你参考的开源uno-online项目基于react-router-dom v5开发,v5会自动向路由渲染的组件注入location/match/history路由属性;但你当前项目安装的是react-router-dom v6,v6取消了默认注入路由props的逻辑,函数组件入参拿到的是空值,访问props.location时自然触发undefined读取错误。
修复方案
二选一即可,优先选第一种官方推荐的Hook方案,改造成本最低。
方案1:使用v6内置路由Hook获取参数(推荐)
v6提供了专用Hook直接读取路由信息,完全不需要依赖props传递:
- 第一步:在Game组件顶部引入useLocation Hook
import { useLocation } from 'react-router-dom'
- 第二步:替换原有props读取location的逻辑,Game组件不需要再接收props参数
const Game = () => { const location = useLocation() const data = queryString.parse(location.search) // 以下原有状态逻辑完全不用改动 const [room, setRoom] = useState(data.roomCode) const [roomFull, setRoomFull] = useState(false) const [users, setUsers] = useState([]) // ....其余业务代码 }
该方案不需要修改App.js中的路由配置,保持<Route path='/play' element={<Game />} />的写法即可正常运行。
方案2:封装withRouter高阶组件兼容旧写法
如果想完全保留原有props读取路由属性的编码习惯,可以手动实现v5版本的withRouter注入逻辑:
- 第一步:封装高阶组件,可以单独存为工具文件,也可以直接写在App.js顶部
import { useLocation, useNavigate, useParams } from 'react-router-dom' const withRouter = (WrappedComponent) => { return (props) => { const location = useLocation() const navigate = useNavigate() const params = useParams() return <WrappedComponent {...props} location={location} navigate={navigate} params={params} /> } }
- 第二步:在Game.js中引入withRouter,导出组件时做一层包裹
export default withRouter(Game)
包裹后组件就能正常通过props.location拿到路由信息,原有业务逻辑不需要改动。
适配提示
后续如果需要做路由跳转,v5的props.history.push写法在v6中已经废弃,需要用useNavigate Hook拿到navigate方法后调用,比如navigate('/')就能跳回首页。
不要为了适配旧代码强行降级react-router-dom到v5,v6的路由性能、API易用性都优于v5,优先用Hook方案适配。
内容的提问来源于stack exchange,提问作者Arjunsshah513
相关产品推荐
相关产品推荐

