Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem with dispatchMultiple #91

Closed
GOVYANSONG opened this issue Feb 6, 2018 · 4 comments
Closed

Problem with dispatchMultiple #91

GOVYANSONG opened this issue Feb 6, 2018 · 4 comments

Comments

@GOVYANSONG
Copy link

I am trying out this option. Typescript source code is attached below:

=======================
import { createAction, handleActions } from 'redux-actions'
import { createLogic } from 'redux-logic';
import { Observable } from 'rxjs'

// -----------------
// STATE - This defines the type of data maintained in the Redux store.

export interface WeatherForecastsState {
isLoading: boolean;
startDateIndex?: number;
forecasts: WeatherForecast[];
}

export interface WeatherForecast {
dateFormatted: string;
temperatureC: number;
temperatureF: number;
summary: string;
}

// -----------------
// ACTIONS - These are serializable (hence replayable) descriptions of state transitions.
// They do not themselves have any side-effects; they just describe something that is going to happen.

enum WeatherForecastsActions {
WEATHERLOGIC_MAIN = 'WEATHERLOGIC_MAIN',
REQUEST_WEATHER_FORECASTS = 'REQUEST_WEATHER_FORECASTS',
RECEIVE_WEATHER_FORECASTS = 'RECEIVE_WEATHER_FORECASTS',
RECEIVE_FAILED = 'RECEIVE_FAILED'
}

//
const fetchFulfilled = createAction(WeatherForecastsActions.RECEIVE_WEATHER_FORECASTS);

const fetchRejected = (params) => ({
type: WeatherForecastsActions.RECEIVE_FAILED,
payload: params,
error: true
});

const ReqStart = createAction(WeatherForecastsActions.REQUEST_WEATHER_FORECASTS);
const ReqMain = createAction(WeatherForecastsActions.WEATHERLOGIC_MAIN);
export const actionCreators = { ReqMain };

// ----------------
export const weatherLogic = createLogic({
//
type: WeatherForecastsActions.WEATHERLOGIC_MAIN,
latest: true,
warnTimeout: 0,
//
processOptions: {
dispatchMultiple: true // turn on multiple dispatch mode
},
//
process({ httpClient, action, getState, store}, dispatch, done) {
//
let startDateIndex: number = action.payload;
//
if (startDateIndex !== getState().weatherForecasts.startDateIndex) {
//dispatch(ReqStart(startDateIndex));
const ob1$ = Observable.of(ReqStart(startDateIndex));
dispatch(ob1$);

        const ob2$ = Observable.create(obs => {
            Promise.all([
                httpClient.get(`api/SampleData/WeatherForecasts?startDateIndex=${startDateIndex}`)
                    .then(resp => resp.data)
                    .then(data => obs.next(fetchFulfilled({ data: data, startDateIndex: startDateIndex }))
                    //console.log(data)
                    //dispatch(fetchFulfilled({ data: data, startDateIndex: startDateIndex }))
                    )
            ]).then(values => obs.complete()); // values dispatched
        });

        dispatch(ob2$);
    }
    //
    done();
}

});

// Note:
// object that is returned will be dispatched to the respective action creator function which takes appropriate parameters

//export const weatherLogic = createLogic({
// //
// type: WeatherForecastsActions.WEATHERLOGIC_MAIN,
// latest: true,
// //
// processOptions: {
// dispatchReturn: true,
// successType: fetchFulfilled,
// failType: fetchRejected
// },
// //
// async process({ httpClient, action, getState }, dispatch) {
// let startDateIndex: number = action.payload;
// if (startDateIndex !== getState().weatherForecasts.startDateIndex) {
// const data = await httpClient.get(api/SampleData/WeatherForecasts?startDateIndex=${startDateIndex})
// .then(resp => resp.data);

// return { data: data, startDateIndex: startDateIndex };
// }
// }
//});

// ----------------
export const reducer = handleActions(
{
[WeatherForecastsActions.REQUEST_WEATHER_FORECASTS]: (state, action) =>
{
return {
startDateIndex: action.payload,
forecasts: state.forecasts,
isLoading: true
};
},

    [WeatherForecastsActions.RECEIVE_WEATHER_FORECASTS]: (state, action) =>
    {
        //if (action.payload.startDateIndex === state.startDateIndex) {
            return {
                startDateIndex: action.payload.startDateIndex,
                forecasts: action.payload.data,
                isLoading: false
            };
        //}
    },

    [WeatherForecastsActions.RECEIVE_FAILED]: (state, action) => {
        //if (action.payload.startDateIndex === state.startDateIndex) {
            return {
                startDateIndex: 0,
                forecasts: [],
                isLoading: false
            };
        //}
    }

}, { forecasts: [], isLoading: false, startDateIndex: 0});

====================

In the process method of weatherLogic, i have two observables: one for a normal action and the other one is for axios API call. The ReqStart action invokes reducer to set loading flag to true. Then the axios API call fetches data from server. The strange thing is that I can dispatch either independently and it works. But if i dispatch both one after another as shown in the source code above, the fetchFulfilled action seems never dispatched to reducer to display the list. I am at a loss what the cause would be.

Thanks for your time.

@GOVYANSONG
Copy link
Author

While I was reviewing other topics in the issue section. I saw a similar one: #18. The resolution made me believe that redux-logic should function for multiple dispatching. In my case, I have a axios api call along with a normal action. Does it make any difference?

@GOVYANSONG
Copy link
Author

More information about my environment:

"rxjs": "5.5.6",
"axios": "0.17.1",
"redux-logic": "0.12.3",
"redux": "3.7.1",

@GOVYANSONG
Copy link
Author

More information on the redux-logic internal monitoring:

09:18:06.560 configureStore.ts:23 Object {action: Object, op: "top"}
09:18:06.563 configureStore.ts:23 Object {nextAction: Object, op: "bottom"}
09:18:06.570 configureStore.ts:23 Object {action: Object, op: "top"}
09:18:06.571 configureStore.ts:23 Object {action: Object, name: "L(WEATHERLOGIC_MAIN)-1", op: "begin"}
09:18:06.573 configureStore.ts:23 Object {action: Object, nextAction: Object, name: "L(WEATHERLOGIC_MAIN)-1", shouldProcess: true, op: "next"}
09:18:06.575 configureStore.ts:23 Object {nextAction: Object, op: "bottom"}
09:18:06.578 configureStore.ts:23 Object {action: Object, dispAction: Object, op: "dispatch"}
09:18:06.581 configureStore.ts:23 Object {action: Object, op: "top"}
09:18:06.583 configureStore.ts:23 Object {nextAction: Object, op: "bottom"}
09:18:06.588 configureStore.ts:23 Object {action: Object, op: "top"}
09:18:06.592 configureStore.ts:23 Object {action: Object, name: "L(WEATHERLOGIC_MAIN)-1", op: "begin"}
09:18:06.593 configureStore.ts:23 Object {action: Object, nextAction: Object, name: "L(WEATHERLOGIC_MAIN)-1", shouldProcess: true, op: "next"}
09:18:06.595 configureStore.ts:23 Object {nextAction: Object, op: "bottom"}
09:18:06.597 configureStore.ts:23 Object {action: Object, name: "L(WEATHERLOGIC_MAIN)-1", op: "end"}
09:18:06.599 configureStore.ts:23 Object {action: Object, name: "L(WEATHERLOGIC_MAIN)-1", op: "dispCancelled"}
09:18:06.601 configureStore.ts:23 Object {action: Object, name: "L(WEATHERLOGIC_MAIN)-1", op: "end"}

Also, from network tab in chrome dev tools, i can see the XHR API call to my server was fulfilled with data.

@GOVYANSONG
Copy link
Author

More observations: if i remove latest: true, both dispatches worked in sequential manner as expected.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant