未捕获的TypeError:无法读取未定义的属性'push'(React-Router-Dom)

时间:2017-05-16 19:05:56

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

我有一个带有旋转幻灯片的信息中心,每张幻灯片都在 Bldgs 中有相应的标签。 Dashboard.jsBldgs.js都是App.js的孩子。

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

相信我将正确的索引值从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;

6 个答案:

答案 0 :(得分:38)

要在history组件中使用App,请将其与withRouter一起使用。仅当您的组件未收到withRouter

时,才需要使用Router props

如果您的组件是由路由器呈现的组件的嵌套子项<或> 您尚未通过路由器道具,则可能发生这种情况。 当组件未完全链接到路由器时,将其作为路径中的单独组件呈现。

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);
withRouter

Documentation

答案 1 :(得分:8)

适用于React-router V4 将功能更改为

<head>

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

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

稍后将其导出为:

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

答案 2 :(得分:0)

您正在尝试不将任务分配给有效的库。在App.js上

所以: 在App.js上

您正在使用BrowserRouter,该浏览器默认情况下处理页面的历史记录,使用此react-router-dom函数,您依靠BrowserRouter来完成此任务。

使用路由器而不是BrowserRouter来控制您的历史记录,并使用历史记录来控制行为。

  1. 使用npm历史记录“ yarn add history@4.x.x” /“ npm i history@4.x.x”
  2. 从“ react-router-dom”导入路线; //不要使用BrowserRouter
  3. 从'createBrowserHistory'导入createBrowserHistory;

请记住将其导出!! 导出const历史= createBrowserHistory();

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

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

答案 3 :(得分:0)

请参阅下面的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>

答案 4 :(得分:0)

我们可以使用useHistory()来历史记录推送方法

add_action( 'woocommerce_thankyou', 'deliverr_api_shipping_options_js' );
function deliverr_api_shipping_options_js( $order_id ) {
    // Get the WC_Order Object instance from order id
    $order     = wc_get_order( $order_id );

    $seller_id = 'deliverr-seller'; // ? !!! - to be defined

    $skus      = array(); // Initializing

    // Loop through order items
    foreach ( $order->get_items() as $item ) {
        $product = $item->get_product(); // Get the WC_Product Object instance
        $skus[]  = $product->get_sku(); // Add each product sku to the array
    }

    ?><script type="text/javascript">
    jQuery( function($){
        window.DeliverrApi.getShippingOptions({
            destination: {
                street1: "<?php echo $order->get_shipping_address_1(); ?>",
                street2: "<?php echo $order->get_shipping_address_2(); ?>",
                zip: "<?php echo $order->get_shipping_postcode(); ?>",
                city: "<?php echo $order->get_shipping_city(); ?>",
                state: "<?php echo $order->get_shipping_state(); ?>",
                country: "<?php echo $order->get_shipping_country(); ?>"
            }<?php if( ! empty($skus) ) { ?>,
            skus: [
                "<?php echo implode('", "', $skus); ?>"
            ]<?php }
            if( ! empty($seller_id) ) { ?>,
            sellerId: "deliverr-seller"
            <?php } ?>
        });
    });
    </script>
    <?php
}

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

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

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

  let history = useHistory();

答案 5 :(得分:0)

我的错误是与 BrowserRouter 一起导入错误,即:

不正确:

import { useHistory } from 'react-router'

正确:

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