ReactJS按钮导航组件报错:Cannot read property 'replace' of undefined
history.replace undefined的问题 看起来你遇到的问题是组件没拿到history对象,所以调用replace方法时才会报错Cannot read property 'replace' of undefined。我来给你梳理几种常见的解决办法:
先搞清楚问题根源
只有被React Router的<Route>组件直接渲染的组件,或者经过特定方式包装的组件,才能自动获取到history这个props。你的Search组件大概率没满足这个条件,所以this.props.history才是undefined。
针对不同React Router版本的解决方案
如果你用的是React Router v5及更低版本
方法1:确保组件被<Route>直接渲染
检查你的路由配置,是不是像下面这样直接把Search组件传给component属性:
import { Route } from 'react-router-dom'; import Search from './Search'; // 在路由配置里 <Route path="/your-search-path" component={Search} />
这样渲染的组件会自动接收history、location、match这三个props,你的按钮点击逻辑就能正常工作了。
方法2:用withRouter高阶组件包装组件
如果Search不是被<Route>直接渲染的(比如是作为子组件被其他组件调用),那就用withRouter来包装它:
- 先导入
withRouter:
import { withRouter } from 'react-router-dom';
- 导出组件时用
withRouter包裹:
class Search extends React.Component { // 你的组件代码 } export default withRouter(Search);
包装之后,this.props.history就能正常访问了。
如果你用的是React Router v6版本
v6里已经移除了withRouter,也不再自动给组件传递history等props,推荐用useNavigate钩子来实现跳转。如果你的组件是类组件,有两种选择:
选择1:把类组件改成函数组件
这是最推荐的方式,适配v6的新特性:
import { useNavigate } from 'react-router-dom'; import { useState } from 'react'; function Search() { const navigate = useNavigate(); // 用useState替代原来的state逻辑 const [hide, setHide] = useState(false); return ( <> {hide && ( <button style={{ background: "green", color: "white" }} onClick={() => navigate('/questions')} > Send Question </button> )} </> ); } export default Search;
选择2:自定义一个withRouter高阶组件适配类组件
如果不想改函数组件,可以自己写个简单的HOC来给类组件传递导航能力:
import { useNavigate, useLocation, useParams } from 'react-router-dom'; import React from 'react'; const withRouter = (Component) => { const Wrapper = (props) => { const navigate = useNavigate(); const location = useLocation(); const params = useParams(); return <Component {...props} navigate={navigate} location={location} params={params} />; }; return Wrapper; }; // 用这个自定义的withRouter包装你的类组件 class Search extends React.Component { handleClick = () => { this.props.navigate('/questions'); }; render() { return ( <> {this.state.hide && ( <button style={{ background: "green", color: "white" }} onClick={this.handleClick} > Send Question </button> )} </> ); } } export default withRouter(Search);
另外提个小细节:你的代码里是{(this.state.hide) && (...)},意思是当hide为true时显示按钮,是不是和你预期的逻辑反了?如果是想隐藏的时候不显示、显示的时候才出现,可能要改成{!this.state.hide && (...)},这个可以根据你的实际需求调整~
内容的提问来源于stack exchange,提问作者M.A.G

