J
J
Jedi2019-02-13 03:58:20
React
Jedi, 2019-02-13 03:58:20

Error: Cannot read property 'push' of undefined how to solve?

Good day!
Please help me solve the problem.
I implemented Authorization according to this tutorial.
Everything works correctly, smoothly, but there is one missed mistake by the author. In App.js, in addition to setToken, the token is checked for validity, and if the token is already out of date, then logout () will simply be dispatched.
The problem is that an error appears: Cannot read property 'push' of undefined .
But if you click on the logout button in the menu, then everything works as it should.
See below is the code.
app.js

import React, { Component } from 'react';
import { BrowserRouter as Router, Route } from 'react-router-dom';
import { Provider } from 'react-redux';
import store from './store';
import jwt_decode from 'jwt-decode';
import setAuthToken from './setAuthToken';
import { setCurrentUser, logoutUser } from './actions/authentication';

import Navbar from './components/Navbar';
import Register from './components/Register';
import Login from './components/Login';
import Home from './components/Home';

import 'bootstrap/dist/css/bootstrap.min.css';

if(localStorage.jwtToken) {
  setAuthToken(localStorage.jwtToken);
  const decoded = jwt_decode(localStorage.jwtToken);
  store.dispatch(setCurrentUser(decoded));

  const currentTime = Date.now() / 1000;
  if(decoded.exp < currentTime) {
    store.dispatch(logoutUser());
    window.location.href = '/login'
  }
}

class App extends Component {
  render() {
    return (
      <Provider store = { store }>
        <Router>
            <div>
              <Navbar />
                <Route exact path="/" component={ Home } />
                <div className="container">
                  <Route exact path="/register" component={ Register } />
                  <Route exact path="/login" component={ Login } />
                </div>
            </div>
          </Router>
        </Provider>
    );
  }
}

export default App;

Menu.js (Everything works here)
import React, { Component } from "react";
import {Link} from "react-router-dom";
import { connect } from "react-redux"
import { withRouter } from "react-router-dom"
import PropTypes from "prop-types"
import {logoutUser} from "../actions/authentication";

class Menu extends Component {
    onLogout(e) {
        e.preventDefault()
        this.props.logoutUser(this.props.history)
    }

    render() {
        const {isAuthenticated, user} = this.props.auth

        const authLinks = (
            <ul className="navbar-nav ml-auto">
                <li className="nav-item">
                    <a className="nav-link" href="#" onClick={this.onLogout.bind(this)}>Выйти</a>
                </li>
            </ul>
        )

        const guestLinks = (
            <ul className="navbar-nav ml-auto">
                <li className="nav-item">
                    <Link className="nav-link" to="/login">Войти</Link>
                </li>
                <li className="nav-item">
                    <Link className="nav-link" to="/register">Регистрация</Link>
                </li>
            </ul>
        )

        return (
            <nav className="navbar navbar-expand-lg navbar-light bg-light">
                <a className="navbar-brand" href="#">StandCars</a>
                <button className="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent"
                        aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
                    <span className="navbar-toggler-icon"></span>
                </button>

                <div className="collapse navbar-collapse" id="navbarSupportedContent">
                    <ul className="navbar-nav mr-auto">
                        <li className="nav-item active">
                            <Link className="nav-link" to="/">Главная</Link>
                        </li>
                        <li className="nav-item">
                            <Link className="nav-link" to="/cars">Cars</Link>
                        </li>
                    </ul>
                    {isAuthenticated ? authLinks : guestLinks}
                </div>
            </nav>
        )
    }
}

Menu.propTypes = {
    logoutUser: PropTypes.func.isRequired,
    auth: PropTypes.object.isRequired,
}

const mapStateToProps = (state) => ({
    auth: state.auth,
})

export default connect(mapStateToProps, {logoutUser})(withRouter(Menu))

auth.js (logoutUser() lives here)
import setAuthToken from "../common/setAuthToken"
import { GET_ERRORS, SET_CURRENT_USER } from "./types"
import axios from "axios"
import jwt from "jwt-decode"

export const registerUser = (user, history) => dispatch => {
    axios.post('/api/auth/register', user).then(function (response) {
            console.log(response);
            history.push("/login")
        })
        .catch(function (error) {
            console.log(error);
        });
}

export const loginUser = (user) => dispatch => {
    axios.post("/api/auth/login", user)
        .then(response => {
            console.log(response.data)
            const { access_token } = response.data
            localStorage.setItem("jwtToken", access_token)
            setAuthToken(access_token)
            const decoded_jwt = jwt(access_token)
            dispatch(setCurrentUser(decoded_jwt))
        }).catch(function (error) {
            console.log(error)
    })
}

export const setCurrentUser = (decoded_jwt) => {
    return {
        type: SET_CURRENT_USER,
        payload: decoded_jwt,
    }
}

export const logoutUser = (history) => dispatch => {
    localStorage.removeItem("jwtToken")
    setAuthToken(false)
    dispatch(setCurrentUser({}))
    history.push('/login')
}

Look please. No matter how much I tried, nothing came of it. I'm new to Redux, I don't really understand what's going on and in what situation.
Thank you very much in advance!

Answer the question

In order to leave comments, you need to log in

1 answer(s)
P
polarlord, 2019-02-13
@PHPjedi

This code works: This code raises an error (a method is called on an argument that was not passed): Try to pass what he wants in logoutUser(), or refer to this argument by condition in it:

if (history !== 'undefined') {
  history.push('/login')
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question