【问题标题】:× history.props.push() getting "TypeError: Cannot read property 'push' of undefined" even when wrapping component in withRouter()× history.props.push() 得到“TypeError: Cannot read property 'push' of undefined”,即使将组件包装在 withRouter()
【发布时间】:2020-11-12 07:14:26
【问题描述】:

我正在尝试用户浏览器路由以在我的应用程序中呈现不同的组件。 使用本教程作为参考:https://www.youtube.com/watch?v=Nq9RmAB9eag

当我尝试使用 this.props.history.push('Path I want to go to') 我得到 TypeError: Cannot read property 'push' of undefined。常见的解决方案是使用 withRouter() 包装组件,但我已经这样做了,但我仍然收到错误。

我也尝试过重定向到与“/”不同的路径。

我在不同的组件中使用了相同的功能,它工作正常。

这是错误:

TypeError: Cannot read property 'push' of undefined
AuthenticatedComponent.render
C:/Users/Liam/Desktop/appFolder/client/src/components/AuthenticatedComponent.js:41
  38 | 
  39 |  render() {
  40 |    console.log(this.state);
> 41 |    this.props.history.push('/');
     | ^  42 |    if (this.state.user === undefined) {
  43 |      return (
  44 |        <div><h1>Loading...</h1></div>

这里是非工作组件的代码(AuthenticatedComponent.js)

import React, { Component } from 'react';
import { getJwt } from '../utilities/jwt'
import { withRouter } from 'react-router-dom'
import axios from 'axios'

export class AuthenticatedComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      user: undefined
    };
  }

  componentDidMount() {
    const jwt = getJwt();
    if (!jwt) {
      // If no JWT token, bring user back to login page (currently root)
      this.props.history.push('/');
    }



    axios.get('api/getUser', { headers: { "auth-token": jwt } }).then((res) => {
      this.setState({user: res.data})

    }
    ).catch(err => {

      console.log("An error occurred getting user: ", err);
      localStorage.removeItem('jwt');
      // Redirect to login
      this.props.history.push('/');
    });


  }

  render() {
    console.log(this.state);
    if (this.state.user === undefined) {
      return (
        <div><h1>Loading...</h1></div>
      )
    }
    return (
      <div>{this.props.children}</div>
    );
  }
}
export default withRouter(AuthenticatedComponent);

这里是 app.js

import React from 'react';
import { LoginContainer } from './components/LoginForm/LoginContainer';
import { AuthenticatedComponent } from './components/AuthenticatedComponent'
import { BrowserRouter, Switch, Route } from 'react-router-dom';
import Protected from './components/ProtectedExample'

class App extends React.Component {
  render() {
    return (
      <BrowserRouter>
        <Switch>
          <Route path="/" exact component={LoginContainer} />
          <AuthenticatedComponent>
            <Route path="/Protected" component={Protected} />
          </AuthenticatedComponent>
        </Switch>
      </BrowserRouter>

    )
  }
}

export default App;

【问题讨论】:

    标签: javascript node.js reactjs


    【解决方案1】:

    这可以解决您的问题:

    import React from 'react';
    import { LoginContainer } from './components/LoginForm/LoginContainer';
    import { AuthenticatedComponent } from './components/AuthenticatedComponent'
    import { BrowserRouter, Switch, Route } from 'react-router-dom';
    import Protected from './components/ProtectedExample'
    
    class App extends React.Component {
      render() {
        return (
          <BrowserRouter>
            <Switch>
              <Route path="/" exact component={LoginContainer} />
              <Route 
                path="/Protected" 
                render={props => (
                  <AuthenticatedComponent history={props.history}>
                    <Protected/>
                  </AuthenticatedComponent>
                )}
              />
            </Switch>
          </BrowserRouter>
        )
      }
    }
    
    export default App;
    

    另一种解决方案是安装 history 包,以便访问 Route 组件之外的“历史”。

    有关后者的更多信息,请查看此 SO 答案:How to Access History Object Outside of a React Component

    【讨论】:

    • 你能解释一下你做了什么吗?
    • 谢谢!这行得通。不过我很好奇,你知道为什么 history.push() 在单独的组件中工作,而不是在 auth 组件中工作吗?
    • 上下文在提交函数MainLogin.js中调用,从LoginContainer.js返回,在app.js中渲染。
    • @CristianTraìna 当然。这有点简单。包装 的组件不会从 react-router 传递道具,例如“位置”或“历史”。因此,为了让 AuthenticatedComponent 访问这些道具,它需要使用“Route”中的“render”道具进行传递。
    • @L.O'Shea 这是因为当您使用“component={LoginContainer}”时,您会将所有 react-router 道具传递给该组件。和声明一样:"render={props => }"
    【解决方案2】:

    您必须向浏览器路由器提供历史记录,

    import { createBrowserHistory } from 'history';
    
    ...
    
    const browserHistory = createBrowserHistory();
    
    return   <BrowserRouter history={browserHistory}> 
    ...
    </BrowserRouter>
    

    【讨论】:

    • 我试过这个但得到了同样的错误:` import { createBrowserHistory } from 'history';类 App 扩展 React.Component { render() { const browserHistory = createBrowserHistory(); return ( ) } } ` 抱歉代码降价似乎不起作用
    猜你喜欢
    • 2018-05-26
    • 1970-01-01
    • 2021-06-25
    • 2017-08-19
    • 1970-01-01
    • 2017-04-24
    • 2023-03-15
    • 2023-02-22
    • 2019-08-13
    相关资源
    最近更新 更多