React Router报Cannot read property 'getCurrentLocation' of undefined如何解决
问题定位与修复方案
错误根因梳理
- 初始版本你使用的是早已废弃的React Router v3版本写法,
browserHistory直接导出的用法在v4及以后的react-router-dom中已经移除,路由嵌套结构也完全不符合规范,这就是getCurrentLocation报错的直接原因 - 修改后的版本仍然嵌套了两层路由根组件(
BrowserRouter和Router)属于冗余错误,同时路由匹配逻辑缺失,跳转方式也不符合新版本规范 - ReviewCard组件存在逻辑错误:作为列表项渲染时不应该再次遍历所有review数据
分步修复代码
1. 修复App.js路由配置(基于react-router-dom v5版本,目前市面常用版本)
import React from 'react'; import ReviewCollection from './components/ReviewCollection'; import ReviewCard from './components/ReviewCard'; import { BrowserRouter, Switch, Route } from 'react-router-dom'; class App extends React.Component { render() { return ( <BrowserRouter> {/* Switch用来保证同一时间只匹配一个路由 */} <Switch> {/* 首页路由匹配点评列表 */} <Route exact path="/" component={ReviewCollection} /> {/* 详情页路由加参数,用来传递点评id,比本地存储更可靠 */} <Route path="/details/:reviewId" component={ReviewCard} /> </Switch> </BrowserRouter> ); } } export default App;
2. 修复ReviewCollection的跳转逻辑
不要直接导入不存在的browserHistory,类组件用withRouter高阶组件注入路由属性即可:
import React from 'react'; import ReviewCard from './ReviewCard'; import { reviews } from '../data'; import { withRouter } from 'react-router-dom'; // 导入withRouter class ReviewCollection extends React.Component { goToDetails = (review) => { // 把点评id拼在路由里跳转,不需要本地存储 this.props.history.push(`/details/${review.id}`); }; render() { return ( <div className='card-collection'> {reviews .filter((review, idx) => idx < 24) .map((review) => ( <div onClick={() => this.goToDetails(review)} key={review.id}> <ReviewCard review={review} isList={true} /> {/* 加个标记区分是列表项还是详情页 */} </div> ))} </div> ) } } // 用withRouter包裹组件,注入history、location等路由属性 export default withRouter(ReviewCollection);
3. 修复ReviewCard的渲染逻辑
区分列表项和详情页的渲染场景,详情页从路由参数拿id找对应点评:
import React from 'react'; import { reviews } from '../data'; import StarRatings from 'react-star-ratings'; import { withRouter } from 'react-router-dom'; import './Review.css'; const ReviewCard = ({ review, isList, match }) => { // 如果是详情页场景,从路由参数拿id找对应review const targetReview = isList ? review : reviews.find(item => item.id === match.params.reviewId); if (!targetReview) return <div>点评不存在</div>; return ( <div className={isList ? "card" : "card-deck"}> <div key={targetReview.id}> <h4 className="card-title">{targetReview.place}</h4> <StarRatings rating={targetReview.rating} starRatedColor="gold" starDimension="20px" /> <div className="card-body">{targetReview.content}</div> <div className="card-footer">{targetReview.author} - {targetReview.published_at}</div> </div> </div> ); }; // 详情页需要拿路由参数,同样用withRouter包裹 export default withRouter(ReviewCard);
额外注意事项
- 所有路由相关的API都从
react-router-dom导入,不需要再安装react-router依赖 - React中class属性要写为
className,你原代码里的class=是不符合React规范的写法,已在上面的代码中修正 - 如果使用的是React Router v6版本,语法会有差异,需要把
Switch换成Routes,component属性换成element属性,跳转用useNavigatehook即可
内容的提问来源于stack exchange,提问作者user16644688
相关产品推荐
相关产品推荐

