【问题标题】:Uncaught TypeError: Cannot read property 'push' of undefined (React-Router-Dom)未捕获的类型错误:无法读取未定义的属性“推送”(React-Router-Dom)
【发布时间】:2018-10-19 13:07:07
【问题描述】:

我有一个带有旋转幻灯片的仪表板,每个幻灯片在Bldgs中都有一个对应的选项卡。 Dashboard.jsBldgs.js 都是我的 App.js 的孩子。

当用户点击Dashboard.js 中的特定幻灯片A 时,Dashboard 需要告诉App.js,以便App 可以告诉Bldgs.js 在路由到@ 时显示标签A 987654332@.

相信我将正确的索引值从Dashboard 向上传递到App 并向下传递到Bldgs。但是,我的App.js 文件中出现了一个错误,说明:

Uncaught TypeError: Cannot read property 'push' of undefined

在我开始将handleClick() 函数传递给Dashboard 组件之前,我的代码运行良好。

Index.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import './index.css';
import injectTapEventPlugin from 'react-tap-event-plugin';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import { BrowserRouter as Router } from 'react-router-dom';
import { hashHistory } from 'react-router';

// Needed for onTouchTap
// http://stackoverflow.com/a/34015469/988941
injectTapEventPlugin();

ReactDOM.render(
  <MuiThemeProvider>
    <Router history={hashHistory}>
      <App />
    </Router>
  </MuiThemeProvider>,
  document.getElementById('root')
);

App.js

import React from 'react';
import { Route } from 'react-router-dom';
import Dashboard from './Dashboard';
import Bldgs from './Bldgs';

var selectedTab;

class App extends React.Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
    selectedTab = 0;
  }

  handleClick(value) {
    selectedTab = value;
    // console.log(selectedTab);
    this.props.history.push('/Bldgs');
    // console.log(this.props);
  }

  render() {
    var _this = this;

    return (
      <div>
        <Route exact path="/" render={(props) => <Dashboard {...props} handleClick={_this.handleClick} />} />
        <Route path="/Bldgs" component={Bldgs} curTab={selectedTab} />
      </div>
    );
  }
}

export default App;

Dashboard.js

import React, { Component } from 'react';
import './Dashboard.css';
import { AutoRotatingCarousel, Slide } from 'material-auto-rotating-carousel';
...

var curIndex;

class Dashboard extends Component {
  constructor(props) {
    super(props);
    this.handleEnter = this.handleEnter.bind(this);
    this.handleChange = this.handleChange.bind(this);
    curIndex = 0;
  }

  handleEnter(e) {
    // console.log(curIndex);
    this.props.handleClick(curIndex);
  }

  handleChange(value) {
    // console.log(value);
    curIndex = value;
  }

...
}

export default Dashboard;

Bldgs.js

...
var curTab;

class Bldgs extends Component {
  constructor(props) {
    super(props);
    this.handleChange = this.handleChange.bind(this);
    this.goHome = this.goHome.bind(this);
    curTab = 0;
  }

  handleChange(value) {
    this.setState({'selectedTab': value});
    console.log(this.state);
  }

  goHome(e) {
    this.props.history.push('/');
  }

...
}

export default Bldgs;

【问题讨论】:

标签: javascript reactjs react-router react-router-dom


【解决方案1】:

为了在App 组件中使用history,请将其与withRouter 一起使用。只有当你的组件没有收到Router props时,你才需要使用withRouter

这可能发生在以下情况下:您的组件是 Router 渲染的组件的嵌套子组件您尚未将 Router 属性传递给它当组件根本没有链接到路由器时,并且呈现为与路由分开的组件。

import React from 'react';
import { Route , withRouter} from 'react-router-dom';
import Dashboard from './Dashboard';
import Bldgs from './Bldgs';

var selectedTab;

class App extends React.Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
    selectedTab = 0;
  }

  handleClick(value) {
    selectedTab = value;
    // console.log(selectedTab);
    this.props.history.push('/Bldgs');
    // console.log(this.props);
  }

  render() {
    var _this = this;

    return (
      <div>
        <Route exact path="/" render={(props) => <Dashboard {...props} handleClick={_this.handleClick} />} />
        <Route path="/Bldgs" component={Bldgs} curTab={selectedTab} />
      </div>
    );
  }
}

export default withRouter(App);

Documentation on withRouter

【讨论】:

  • 这个小改动让一切正常,但你能解释一下它在做什么吗?谢谢!
  • 添加了描述这一点的 withRouter 文档。
  • 嘿伙计们,现在我们从“react-router”而不是“react-router-dom”导入“withRouter”。文档 - v5.reactrouter.com/web/api/withRouter
【解决方案2】:

适用于 React-router V4 把函数改成

onClick={this.fun.bind(this)}

fun() {
  this.props.history.push("/Home");
}

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

稍后将其导出为:

export default withRouter (comp_name);

【讨论】:

  • 为什么要导入browserHistory
  • 不需要使用bind(this)你可以使用onClick={this.fun}
【解决方案3】:

在使用函数式组件时,我们可以使用 useHistory() to history to push 方法

import { useHistory } from "react-router-dom";

然后在函数中我们必须分配 useHistory()

  let history = useHistory();

现在我们可以使用 history.push 重新定位到所需的页面

history.push('/asdfg')

【讨论】:

  • OP 正在使用类组件,因此无法在其中使用钩子 + 那时,当提出问题时,由于钩子不存在,因此无法使用。
  • 我知道,但我也想为现在也使用钩子的人提供解决方案,这个答案是 3 年前提出的,现在人们已经更多地转向功能组件,问题没有具体说明仅限类组件,所以如果现在人们发现这个问题,希望他们也能找到我的钩子解决方案
  • 我正在做这样的事情,这就是我在这里的原因......
  • 它对我解决问题有很大帮助。谢谢。
【解决方案4】:

您正在尝试推送而不将任务交给有效的库。在 App.js 上

所以: 在 App.js 上

您正在使用默认情况下处理页面历史记录的 BrowserRouter,使用此 react-router-dom 功能,您依赖 BrowserRouter 为您执行此操作。

使用路由器而不是浏览器路由器来控制你的历史,使用历史来控制行为。

  1. 使用 npm history "yarn add history@4.x.x" / "npm i history@4.x.x"
  2. 从'react-router-dom'导入路由; //不要使用浏览器路由器
  3. 从'createBrowserHistory'导入createBrowserHistory;

记得导出!! export const history = createBrowserHistory();

4.将历史记录导入 Dashboard.js 5.导入历史到Bldgs.js

希望这会有所帮助!!! @brunomiyamotto

【讨论】:

    【解决方案5】:

    请参阅下面的 App.js 文件。我最终将 {...this.props} 传递给了我创建的 NavBar 组件。 NavBar 组件不是我的 Switch 路由的一部分。

    import React, { Component } from 'react';
    import { Route, Link, Redirect, Switch, withRouter } from 'react-router-dom'
    
    import Navbar from './Navbar.js';
    import Home from './Home/HomeCont';
    import Login from './Register/Login';
    import Dashboard from './Dashboard/DashboardCont';
    
    
    import './App.css';
    
    class App extends Component {
      constructor(props){
        super(props);
    
      }
    
      render() {
        return (
          <div className="App">
            <header className="App-header">
    
    //SOLUTION!!!
              <Navbar {...this.props}/>
    
    
            </header>
            <Switch>
              <React.Fragment>
                <Route exact path="/" render={(props) => <Home {...props}/>}/>
    
                <Route exact path="/login" render={(props) => <Login {...props}/>}/>
    
    
              </React.Fragment>
    
    
            </Switch>
          </div>
        );
      }
    }
    
    export default withRouter(App);
    

    在我的导航栏中。我使用的按钮有以下代码。我必须 .bind(this) 才能查看历史记录并能够使用 this.props.history.push("/")

    <Button
       color="inherit"
       onClick={this.handleLogout.bind(this)}>Logout</Button>
    

    【讨论】:

      【解决方案6】:

      我的错误是与BrowserRouter 结合使用的错误导入,即:

      不正确:

      import { useHistory } from 'react-router'

      正确:

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

      【讨论】:

        【解决方案7】:

        我通过将组件包装在 BrowserRouter 中解决了这个错误。
        不要忘记这一点,这是一个很常见的错误。

        import { BrowserRouter} from 'react-router-dom';
        
        <BrowserRouter>
            <Menu/>
        <BrowserRouter>    
        

        只有路由器子节点接收历史钩子。

        【讨论】:

          猜你喜欢
          • 2017-04-13
          • 2021-09-20
          • 2020-08-23
          • 2018-02-02
          • 2019-09-11
          • 1970-01-01
          • 2017-08-12
          • 2020-07-25
          相关资源
          最近更新 更多