阅读 22

使用React的this.props.history.push()报错解决方案

在使用React的路由跳转时,出现了这个错误"cannot read property 'push' of undefined",找来找去,发现是子组件这样调用时才会报错,它不是路由组件。

该Header组件会在每个页面中引入,使其成为子组件

解决办法:

一、通过父组件传值给子组件

在父组件中,传递一个history给子组件

<Header history={this.props.history} />
复制代码

子组件方法还是一样写

`this.props.history.push('/login')`
复制代码

但如果Header组件被嵌套封装更深的话是不行的,这时只能选择第二种方法。

二、使用withRouter

默认情况下必须经过路由匹配渲染的组件才存在this.props,才拥有路由参数,执行this.props.history.push('/login')跳转到对应路由的页面,然而不是所有组件都直接与路由相连(通过路由跳转到此组件)的,当这些组件需要路由参数时,使用withRouter就可以给此组件传入路由参数,将react-router的history、location、match三个对象传入props对象上,此时就可以使用this.props。

可见当一个非路由组件也想访问到当前路由的match,location,history对象,那么withRouter将是一个非常好的选择,可以理解为将一个组件包裹成路由组件。

用法:

import { withRouter } from 'react-router-dom'

// ...
class Header extends React.Component {
   //...
}

export default withRouter(Header); // export时要使用withRouter
复制代码

在Header组件引入并使用,就可以使用this.props.history.push方法进行正常跳转了

正确的写法:

import React from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import ReactDOM from 'react-dom';
import Header from './components/common/Header';
import List from './components/list/List';
import Detail from './components/detail/Detail';
import NotFound from './components/notfound/NotFound';
import './index.css';

const App = () => {
  return (
    <Router>
      <BasicLayout>
	      <Switch>
	        <Route exact path="/" component={List} />
	        <Route exact path="/currency/:id" component={Detail} />
	        <Route component={NotFound} />
	      </Switch>
      </BasicLayout>
    </Router>
  );
}

ReactDOM.render(<App />, document.getElementById('root'));
123456789101112131415161718192021222324
复制代码

BasicLayout组件的内容如下:

import React from 'react';
import { withRouter } from 'react-router-dom';

function BasicLayout(props) {
	console.log({props}) // history,location等等withRouter附加的props就能看到了

    return (
        <div>
            xxxxx
        </div>
    );
}

export default withRouter(BasicLayout);
复制代码