首页 > 解决方案 > React Redux not updating state despite login working fine

问题描述

So my reducers are not updating the state for my app. The initial state in user shows up with no changes made. The initial state from uiReducer doesn't come up at all. emphasized textI can log in okay and receive a token, so I think it is a problem with getUserData. I have no idea why the ui initial state isn't working however. This is my first time trying to use react redux so I probably have a dumb mistake somewhere. Any help appreciated!

EDIT: Without changing code, I just restarted my app and now both of the initial states are loading, but user is still not populated with data.

login

import React, { Component } from 'react';
import PropTypes from 'prop-types'

// redux
import {connect} from 'react-redux'
import {loginUser} from '../redux/actions/userActions'

class login extends Component {
    constructor(props) {
        super(props);

        this.state = {
            email: '',
            password: '',
            errors: [],
        };
    }

    componentWillReceiveProps(nextProps) {
        if (nextProps.UI.errors) {
            this.setState({
                errors: nextProps.UI.errors
            });
        }
    }

    handleChange = (event) => {
        this.setState({
            [event.target.name]: event.target.value
        });
    };

    handleSubmit = (event) => {
        event.preventDefault();
        const userData = {
            email: this.state.email,
            password: this.state.password
        };
        this.props.loginUser(userData, this.props.history)
    };

    render() {
        const { classes, UI: {loading} } = this.props;
        const { errors } = this.state;
        return (
            ..............
        );
    }
}
login.propTypes = {
    classes: PropTypes.object.isRequired,
    loginUser: PropTypes.func.isRequired,
    user: PropTypes.object.isRequired,
    UI:PropTypes.object.isRequired

}

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

const mapActionsToProps = {
    loginUser
}

export default connect(mapStateToProps, mapActionsToProps)(withStyles(styles)(login));

userActions

import axios from 'axios';

export const loginUser = (userData, history) => (dispatch) => {
    dispatch({ type: 'LOADING_UI' });
    axios
        .post('/login', userData)
        .then((res) => {
            setAuthorizationHeader(res.data.token);
            dispatch(getUserData())
            dispatch({type: 'CLEAR_ERRORS'})
            history.push('/');
        })
        .catch((error) => {             
            dispatch({
                type: 'SET_ERRORS',
                payload: error.response.data
            });
        });

}

export const getUserData = ()=> (dispatch) => {
    axios
        .get('/user')
        .then(res => {
           dispatch({
               type: 'SET_USER',
               payload: res.data
           })
        })

}

const setAuthorizationHeader = (token) => {
    const FBIdToken = `Bearer ${token}`;
    localStorage.setItem('FBIdToken', FBIdToken);
    axios.defaults.headers.common['Authorization'] = FBIdToken;
};

userReducer

const initialState = {
    authenticated: false,
    credentials: {},
    approves: []
}

export default function(state = initialState, action){
    switch(action.type){
        case 'SET_AUTHENTICATED':
            return{
                ...state,
                authenticated: true
            }
        case 'SET_UNAUTHENTICATED':
            return initialState
        case 'SET_USER':
            return{
                authenticated: true,
                loading: false,
                ...action.payload
            }
        default:
            return state
    }
}

uiReducer

const initialState = {
    loading: false,
    errors: null
}
export default function(state = initialState, action) {
    switch (action.type) {
      case 'SET_ERRORS':
        return {
          ...state,
          loading: false,
          errors: action.payload
        };
      case 'CLEAR_ERRORS':
        return {
          ...state,
          loading: false,
          errors: null
        };
      case 'LOADING_UI':
        return {
          ...state,
          loading: true
        };
        default:
            return state
    }
}

I'm really confused that I can log in fine, but the state isnt updated, and only the user state is initialized..

EDIT: store.js

import { createStore, combineReducers, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';

import userReducer from './reducers/userReducer';
import dataReducer from './reducers/dataReducer';
import uiReducer from './reducers/uiReducer';

const initialState = {};

const middleware = [thunk];

const reducers = combineReducers({
  user: userReducer,
  data: dataReducer,
  UI: uiReducer
});



const store = createStore(reducers, 
    initialState, 
    compose(
        applyMiddleware(...middleware),
        window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
    )
);

export default store;

标签: reactjsreduxreact-redux

解决方案


Changing ...action.payload to user: action.payload seems to have fixed it. I got the code for this section from a tutorial but the syntax must have been slightly outdated or something, who knows

export default function(state = initialState, action){
    switch(action.type){
        case 'SET_AUTHENTICATED':
            return{
                ...state,
                authenticated: true
            }
        case 'SET_UNAUTHENTICATED':
            return initialState
        case 'SET_USER':
            return{
                authenticated: true,
                loading: false,
                user: action.payload
            }
        default:
            return state
    }
}

推荐阅读