agraboso / redux-api-middleware

Redux middleware for calling an API.
MIT License
1.49k stars 195 forks source link

Bailout during REQUEST #94

Open mvhecke opened 8 years ago

mvhecke commented 8 years ago

My application consist of multiple components that do a request when they are constructed. The problem is a request should only be done once because otherwise there are multiple requests to the same endpoint. Initially I attempted to get the required state in the bailout method and check if the store was inProgress. After some attempts I however found out that bailout is only checked upon initialization and not checked again pre-action.

Setting inProgress: true on my REQUEST (GIFTS_LOAD) does not work like I expect it to work. Below you can check out my temporary solution to prevent duplicate request from being executed. The reason is that the components listen to the state anyway, thus only a single set of actions should be executed.

The concept behind this is based on the following: http://www.zohaib.me/redux-call-service-async/ http://redux.js.org/docs/advanced/AsyncActions.html (search for shouldFetchPosts)

How can I solve this in a cleaner way or is this how it's supposed to work?

Action

export function getGifts(accountId) {
    return function(dispatch) {
        dispatch({
            [CALL_API]: {
                endpoint: `${baseConfig.apiBaseUrl}${accountId}/gifts/`,
                method: 'GET',
                types: [types.GIFTS_LOAD, types.GIFTS_LOAD_SUCCESS, types.GIFTS_LOAD_FAILURE],
                bailout: (state) => {
                    if (!(state.gift.fetched || state.gift.inProgress)) {
                        dispatch({ type: types.GIFTS_PENDING });
                    }

                    //Cancel request if already in progress
                    return !!(state.gift.fetched || state.gift.inProgress);
                },
                headers,
                credentials: 'same-origin'
            }
        });
    };
}

Reducer

export default function gift (state = initialState, action) {
    switch (action.type) {
        case types.GIFTS_PENDING:
            return {
                ...state,
                inProgress: true
            };
        case types.GIFTS_LOAD_SUCCESS:
            return {
                ...state,
                gifts: action.payload,
                fetched: true,
                inProgress: false,
                error: false
            };
        case types.GIFTS_LOAD_FAILURE:
            return {
                ...state,
                inProgress: false,
                error: true
            };
        case types.CLAIM_GIFT_SUCCESS:
            return {
                ...state,
                gifts: mutate(state, action)
            };
        default:
            return state;
    }
};
edsioufi commented 8 years ago

I had the same issue so I forked the repo and ended up with the above PR.

amangeot commented 8 years ago

Same issue for bailing out when reducer is set to "fetching" upon requests. Did you get to talk to @agraboso by any chance @siouf ?

edsioufi commented 8 years ago

@amangeot no I didn't