reducer.state.props is undefined in nested actions

2019-08-24 11:49发布

问题:

Below are my action and reducer files - In my component state I am only seeing this.props.mainData - but others subdataOneData etc., are not being loaded in to the state - till reducer i see the right actions are being dispatched and I also see the data for sub - calls - but they are not reaching my component - I have mapStatetoprops - where I am doing

New issue: as per the updated code - when i print out payload in reducer - I see maindata with the api data but SubData [{}, {}, {}] ..?

Updated code: import { GET_DATA_AND_SUBDATA } from '../constants/types';

export function getMainData() {
  return async function getMainData(dispatch) {
    const { data } = await getMainDataAPI();
    const subData = data.map((item) => {
      const endpoint = 'build with item.name';
      return Request.get(endpoint);
    });
     console.log('subddd' + subData);  prints -> **[object Promise],[object Promise],[object Promise]**
    dispatch({
      type: GET_DATA_AND_SUBDATA,
      payload: { data, subData }
    });
  };
}

async function getMainDataAPI() {
  const endpoint = 'url';
  return Request.get(endpoint);
}

回答1:

The problem lies on the way you dispatch the actions.

You are not providing data for mainData and subdataOneData at the same time.

export function getData() {
    return async function getData(dispatch) {
        const { data } = await getDataAPI();

        // This will cause first re-render
        dispatch({ type: GET_DATA, payload: data }); 

        Object.keys(data).map((keyName, keyIndex) => {
            const endpoint = 'ENDPOINT';
            Request.get(endpoint).then((response) => {
                // This will cause second re-render
                dispatch({
                    type: GET_subdata + keyIndex,
                    payload: response.data });
                }); 

            return keyIndex;
        });
    };
}

At first render your subdataOneData is not availble yet.

You are not even specifying a default value in the reducer, therefore it will be undefined.

You can change your action thunk like this

export function getData() {
    return async function getData(dispatch) {
        const { data } = await getDataAPI();

        const subDataResponse =  await Promise.all( 
            Object.keys(data).map( () => {
                const endpoint = 'ENDPOINT';
                return Request.get(endpoint)                    
            })
        )

        const subData = subDataResponse.map( response => response.data )

        dispatch({
            type: GET_DATA_AND_SUBDATA
            payload: { data, subData }
        });

    };
}

And change your reducer accordingly in order to set all data at once.

export default function myReducer(state = {}, action) {
    switch (action.type) {
        case GET_DATA_AND_SUBDATA:
        return {
            ...state,
            mainData: action.payload.data,
            subdataOneData: action.payload.subData[0],
            subdataTwoData: action.payload.subData[1]
        };        
        default:
            return state;
    }
}

Note: it's also a good practice to set your initial state in the reducer.

const initialState = {
    mainData: // SET YOUR INITIAL DATA
    subdataOneData: // SET YOUR INITIAL DATA
    subdataTwoData: // SET YOUR INITIAL DATA
}

export default function myReducer(initialState, action) {