React + Redux: TypeError: Невозможно прочитать свойство «push» из неопределенного - PullRequest
0 голосов
/ 11 сентября 2018

Я начинаю с ReactJS и Redux и последние несколько дней у меня возникает проблема, когда я некоторое время оставляю свое приложение открытым в браузере, а затем возвращаюсь к нему, я вижу там эту ошибку: enter image description here

TypeError: Cannot read property 'push' of undefined

Это здесь, в моем Event.js компоненте:

import React, { Component } from 'react';
import axios from 'axios';
import classnames from 'classnames';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { registerUser, logoutUser } from '../redux/actions/authentication';
import { withRouter } from 'react-router-dom';

class Event extends Component {
    constructor() {
        super();
        this.state = {
          ...
        }
    UNSAFE_componentWillMount() {
        if(!this.props.auth.isAuthenticated) {
            console.log('Unauthorized - Event action');
            this.props.history.push('/');
        }
    }
    componentDidMount() {
        axios.get('/api/events')
            .then((response) => {
                this.setState({events: response.data});
                console.log('events: ', this.state.events);
            }).catch(err => {
                console.log('CAUGHT IT! -> ', err);
            });
    }

    componentWillReceiveProps(nextProps) {
        if(nextProps.errors) {
            this.setState({
                errors: nextProps.errors
            });
        }
    }
    ...
    render() {
        const { errors } = this.state;
        const {isAuthenticated, user} = this.props.auth;

        return (...)
    }
Event.propTypes = {
    registerUser: PropTypes.func.isRequired,
    auth: PropTypes.object.isRequired,
    errors: PropTypes.object.isRequired
};

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

export default connect(mapStateToProps,{ registerUser })(withRouter(Event))

Тогда мой redux/actions/authentication.js выглядит так:

import axios from 'axios';
import { GET_ERRORS, SET_CURRENT_USER } from './types'; // we list here the actions we'll use
import setAuthToken from '../../setAuthToken';
import jwt_decode from 'jwt-decode';

export const registerUser = (user, history) => dispatch => {
    axios.post('/api/users/register', user)
            .then(res => history.push('/login'))
            .catch(err => {
                dispatch({
                    type: GET_ERRORS,
                    payload: err.response.data
                });
            });
}

export const loginUser = (user) => dispatch => {
    axios.post('/api/users/login', user)
        .then(res => {
            //console.log(res.data);
            const { token } = res.data;
            localStorage.setItem('jwtToken', token);
            setAuthToken(token);
            const decoded = jwt_decode(token);
            dispatch(setCurrentUser(decoded));
        })
        .catch(err => {
            dispatch({
                type: GET_ERRORS,
                payload: err.response.data
            });
        });
}

export const setCurrentUser = decoded => {
    return {
        type: SET_CURRENT_USER,
        payload: decoded
    }
}

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

И редукторы - authReducer.js:

import { SET_CURRENT_USER } from '../actions/types';
import isEmpty from '../../validation/is-empty';

const initialState = {
    isAuthenticated: false,
    user: {}
}

export default function(state = initialState, action) {
    switch(action.type) {
        case SET_CURRENT_USER:
            return {
                ...state,
                isAuthenticated: !isEmpty(action.payload),
                user: action.payload
            }
        default: 
            return state;
    }
}

errorReducer.js выглядит так:

import { GET_ERRORS } from '../actions/types';

const initialState = {};

export default function(state = initialState, action ) {
    switch(action.type) {
        case GET_ERRORS:
            return action.payload;
        default: 
            return state;
    }
}

и index.js:

import { combineReducers } from 'redux';
import errorReducer from './errorReducer';
import authReducer from './authReducer';

export default combineReducers({
    errors: errorReducer,
    auth: authReducer
});

Вв набере меню, у меня есть ссылка для выхода пользователя.Если пользователь щелкает ссылку, я выхожу из него так:

onLogout(e) {
        e.preventDefault();
        this.props.logoutUser(this.props.history);
    }

Однако я все еще не могу понять, почему я вижу ошибку выше.Здесь я также не понимаю, что когда я получаю этот экран ошибок и затем обновляю страницу, страница ошибок исчезает, и меня перенаправляют с localhost:3000/events на localhost:3000.

Ответы [ 2 ]

0 голосов
/ 11 сентября 2018

Вы должны использовать

withRouter(connect(...)(MyComponent))

а не

connect(...)(withRouter(MyComponent))

вот документация

Я думаю, что this.props.history - это undefined в вашем примере из-за этого.

0 голосов
/ 11 сентября 2018

Убедитесь, что объект, который вы передаете в функцию logoutUser, не является неопределенным, а параметр history получен правильно.Вы пытаетесь вызвать метод push для объекта history, но в этом случае он сообщает, что функция не может быть найдена, поскольку history не определено.Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...