简体   繁体   中英

ReactJS x Redux: Reducer not returning state values

Hi I'm new at React and Redux.

I'm met with a problem with the reducer while trying to fetch a user object from the database. But it seems like it is not returning the state to the correct place?

On my front end :

import { a_fetchUser } from '../../../actions/resident/actions_user';

class EditProfile extends Component {
    componentDidMount() {
       this.props.fetchProfile({ iduser: this.props.auth.user.iduser });
       console.log(this.props.store.get('isProcessing')); // returns false
       console.log(this.props.store.get('retrievedUser')); // returns empty object {} when it's supposed to return data
    }

    // code simplified...

    const mapStateToProps = state => ({
       store: state.r_fetch_user,
       auth: state.authReducer
    });

    const mapDispatchToProps = (dispatch, store) => ({
       fetchProfile: (user) => {
           dispatch(a_fetchUser(user));
       }
    });

    export const EditProfileContainer = connect(
      mapStateToProps,
      mapDispatchToProps,
    )(EditProfile);
}

Action :

import axios from 'axios';

const startFetchUser = () => ({
    type: 'START_FETCH_USER',
});

const endFetchUser = response => ({
    type: 'END_FETCH_USER',
    response,
});

export const a_fetchUser = (user) => (dispatch) => {
    dispatch(startFetchUser());
    return axios.post('/rdb/getUser/', user)
        .then((res) => {
        console.log(res);
        dispatch(endFetchUser(res));
    })
    .catch((err) => {
        console.log(err);
        dispatch(endFetchUser({ status: 'error' }));
    });
};

Reducer :

import Immutable from 'immutable';

export const fetchUserState = Immutable.Map({
    isProcessing: false,
    feedbackType: null,
    feedbackMsg: null,
    retrievedUser: {},
});

export const r_fetch_user = (state = fetchUserState, action) => {
    switch (action.type) {
        case 'START_FETCH_USER':
            console.log('start'); // printed
            return state.set('isProcessing', true);
        case 'END_FETCH_USER':
            if (action.response.data.status === 'success') {
                console.log(action.response.data.data[0]); // data retrieved from database successfully
                return state.set('isProcessing', false).set('retrievedUser', action.response.data.data[0]);
            } else {
                return state.set('isProcessing', false).set('retrievedUser', {});
            }
        default:
            return state;
    }
};

My aim is to retrieve the object retrievedUser from the store. I've tried to console.log(this.props.store) on the front end and it did return a Map of the initial state, fetchUserState.

I've also tried to state.set (without returning) and it was successful so I came to a conclusion that there was something wrong with the return statement?

Additional details: Using MERN stack.

this looks wrong:

 const mapDispatchToProps = (dispatch, store) => ({
       fetchProfile: (user) => {
           dispatch(a_fetchUser(user));
       }
    });

What you need to do is to use bindActionCreators with, you can see example here and here :

function mapDispatchToProps(dispatch) {
  return bindActionCreators(actionCreators, dispatch)
}

or you can also change the syntax to:

 const mapDispatchToProps = (dispatch) => ({
           fetchProfile: a_fetchUser(user);
 });

I am not sure what exactly your state.set() method does (in reducer) but if its mutating the state, then your reducer will not remain PURE function since its changing the original state obj. So please update below reducer method to start returning new state obj which should not mutate existing state obj:

export const r_fetch_user = (state = fetchUserState, action) => {
    switch (action.type) {
        case 'START_FETCH_USER':
            console.log('start'); // printed
            return state.set('isProcessing', true);
        case 'END_FETCH_USER':
            if (action.response.data.status === 'success') {
                console.log(action.response.data.data[0]); // data retrieved from database successfully
                return state.set('isProcessing', false).set('retrievedUser', action.response.data.data[0]);
            } else {
                return state.set('isProcessing', false).set('retrievedUser', {});
            }
        default:
            return state;
    }
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM