Search code examples
reduxreact-reduxredux-thunk

redux dispatch fires multiple times


I'm experiencing following unwanted behaviour in Redux (React/ Redux + redux-thunk): I'm triggering an event (click) which lets an action fire and dispatch some additional data as objects in an array. When I'm clicking the first time the action dispatches once with one object in the array (result 1: one new object) - and that's fine.

But now the unwanted thing happens:

When I'm clicking the second time calling for new additional data the action dispatches twice - first time with the formerly called data in state (result 1) - secondly with the newly called data in state (result 2: two identical objects containing the new data). Having three objects in state now.

When I'm clicking the third time again calling for new data the action dispatches three times first with result 1 secondly with result 2 and the third time with the again-newly called data in state (result 3: three identical objects containing the new data). Having six objects in state now.

...and so on...

My expectation: The action should always fire once and the reducer should add the new data-object once accordingly resulting in that the amount of objects is always equal the the amount clicks.

Here is some code:

The action:

export function getData(idData) {
    return function (dispatch, getState) {
        dispatch({type: "FETCHING_DATA"});
        const socket = getState().socket.socket;
        socket.emit("requestData", idData);
        socket.on("responseData", function(newData){
            console.log("TRIGGER");
            dispatch({type: "GET_DATA", payload: newData});
        });
    }
}

The reducer:

export function priceMonitorReducers(
    state={
        data: [],
        isFetchingData: false,
    }, action) {
    switch (action.type) {
        case "FETCHING_DATA":
            return {...state, isFetchingData: true};
            break;
        case "GET_DATA":
            return {...state,
                data: [...state.data, action.payload],
                isFetchingData: false };
            break;
    }
    return state;
}

The component:

onGetData = (idData) => {
    this.props.getData(idData);
};

function mapStateToProps(state) {
    return {
        data: state.data,
        ...
    }
}

function mapDispatchToProps(dispatch) {
    return bindActionCreators({
        getData: getData
        ...
    }, dispatch);
}

export default connect(mapStateToProps, mapDispatchToProps)(Journey);

Where am I doing or expecting wrong? Your help is much appreciated!


Solution

  • You're registering an extra event handler to the socket on each getData call. Instead, you should register just one handler on initialization and only emit in getData.