React Router v5.2中通过Link传递state后无法获取props,报TypeError错误的解决方法
问题
我在使用React Router v5.2时,没法获取Link组件通过state传递的props,React直接抛出了TypeError: Cannot read property 'state' of undefined的错误。以下是我的相关代码:
跳转发起方:ChooseReserv组件
export default class ChooseReserv extends Component { token = localStorage.getItem('token'); state = {nb: 1, html : []}; test = 0; componentDidMount = () => { axios.get('Parking', {headers: {'Authorization': 'Bearer ' + this.token}}).then( res => { console.log(res.data) this.loadAllUsers(res.data); }, err => { console.log(err); } ) } loadAllUsers = (data) => { for (var i = 0; i < data.length; i++) { var value = ( <div id={data[i].id}> {data[i].name} <button style={{marginLeft: "50px"}} type="button" class="btn btn-secondary"> <Link style={{color: "white"}} className="nav-link" to={{ pathname:'/myReserv', state: { data: data[i] } }}>Go</Link> </button> <p></p> </div> ) this.setState({ html: this.state.html.concat([value]) }) } } render() { var htmle = this.state.html; console.log("html" + htmle); if (this.props.connected == 'false') { return <Redirect to={'/'}/>; } return ( <div> <br></br> <h1>Réserver votre place de parking !</h1> <div className="auth-wrapper"> <div className="auth-inner"> {htmle} </div> </div> </div> ) } }
跳转接收方:MyReserv组件
export default class MyReserv extends Component { token = localStorage.getItem('token'); componentDidMount = () => { console.log(this.props.location.state.data); } render() { if (this.props.connected == 'false') { return <Redirect to={'/'}/>; } return ( <div className="auth-wrapper"> <div className="auth-inner"> <h2>Bienvenue .</h2> </div> </div> ) } }
解决方法
你遇到的这个问题其实是React Router v5里很常见的小坑——只有被<Route>组件直接渲染的组件,才能自动拿到location、history这些路由相关的props。如果你的MyReserv不是直接由路由渲染的,或者路由配置的方式不对,就会出现this.props.location为undefined的情况。
解决这个问题最直接的方式就是用withRouter高阶组件给MyReserv注入路由props,具体步骤如下:
导入
withRouter
在MyReserv组件的文件顶部,从react-router-dom里把withRouter导进来:import { withRouter, Redirect } from 'react-router-dom';用
withRouter包裹组件
把原来的export default MyReserv;改成用withRouter包裹的形式,这样就能把路由相关的props注入到组件里了:export default withRouter(MyReserv);修改后的完整
MyReserv组件代码如下,我还加了容错判断,避免用户直接访问/myReserv路由时(没有通过Link跳转,导致state不存在)再次报错:import { withRouter, Redirect } from 'react-router-dom'; class MyReserv extends Component { token = localStorage.getItem('token'); componentDidMount = () => { // 先判断数据是否存在,再访问 if (this.props.location?.state?.data) { console.log(this.props.location.state.data); } else { console.log("没有接收到传递的数据,可能是直接访问的路由"); } } render() { if (this.props.connected == 'false') { return <Redirect to={'/'}/>; } return ( <div className="auth-wrapper"> <div className="auth-inner"> <h2>Bienvenue .</h2> </div> </div> ) } } export default withRouter(MyReserv);额外检查路由配置
顺便确认一下你的路由配置是否正确,MyReserv需要通过<Route>组件来渲染,比如:<Route path="/myReserv" component={MyReserv} />如果路由配置没问题,那用
withRouter包裹后肯定能拿到locationprops了。
内容的提问来源于stack exchange,提问作者zidanow

