@PHPjedi

Ошибка: Cannot read property 'push' of undefined как решить?

Доброго времени суток!

Помоги пожалуйста решить проблемку.

Я реализовал Авторизацию по этому туториалу.

Все работает правильно, плавно, но есть одна упущенная ошибка автором. В App.js помимо setToken, токен проверяется на срок действие, и если токен уже устарел, то просто диспатчится logout().

Проблема в том, что появляется ошибка: Cannot read property 'push' of undefined .
Но если в меню нажать на кнопку logout, то все работает как надо.

Смотрите, ниже есть код.

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 (Здесь все работает)

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())

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')
}


Посмотрите, пожалуйста. Сколько я не пытался, у меня ничего не вышло. Я новенький в Redux, не очень понимаю, что и в какой ситуации что происходит.

Заранее большое спасибо!
  • Вопрос задан
  • 4088 просмотров
Решения вопроса 1
polarlord
@polarlord
Этот код работает:
this.props.logoutUser(this.props.history)

Этот код вызывает ошибку (вызывается метод у аргумента который не передали):
store.dispatch(logoutUser());

Попробуйте в logoutUser() передавать то что он хочет, либо в нём обращаться к этому аргументу по условию:
if (history !== 'undefined') {
  history.push('/login')
}
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы