Redux updateElementSaga has been canceled. What for?

I just realized the drag function with response-dnd, and when the user dropped the item SkyElement

in my application, I update top

and left

the server, which in turn updates the reductions storage

However, the update call works sometimes, not every time. And in my console I see a warning;updateElementSaga has been cancelled

In my SlotView.js

in function I have:

this.props.dispatch(requestUpdateElement({ id, top, left }));

In my elements/actions.js

:

export function requestUpdateElement(element) {
    return { type: 'requestUpdateElement', element };
}

      

In my elements/sagas.js

:

export function *updateElementSaga(action) {
    const response = yield call(api.updateElement, action.element);

    if (response.element) {
        // debugger; // this hits, saga was cancelled will have appeared in the console at this point
        yield put(actions.receiveElement(response.element));
    } else if (response.error) {
        console.log('error receiving element');
    }
}

export default [
    takeLatest('requestUpdateElement', updateElementSaga),
];

      

In api.js

:

export function updateElement(element) {
    const userId = JSON.parse(localStorage.cookies).userId;
    element.userId = userId;

    if (userId) {
        return apiHelper.put(
            `${apiHelper.getBaseUrl()}/users/${element.userId}/elements/${element.id}`,
            {element},
            {headers: apiHelper.getHeaders()}
        ).catch((error) => {
            return {error};
        });
    } else {
        console.log('user ID could not be found for request');
    }
}

      

And mine elements/reducer.js

:

const defaultState = {
    elementsMap: {},
    visibleElements: [],
    unplacedElements: [],
};

export default function(state = defaultState, action) {
    switch (action.type) {
        case 'receiveElement':
            let element = null;
            let unplacedElement = null;

            if (action.element.sectorId === undefined) {
                unplacedElement = `${action.element.id}`;
            } else {
                element = `${action.element.id}`;

                // don't add, duplicate
                const newState = {...state}; // copy old state
                delete newState[`${action.element.id}`]; // delete the item from the object
                const newVisibleElements = newState.visibleElements.filter(e => e !== `${action.element.id}`); // remove item from visible elements
                const newUnplacedElements = newState.unplacedElements.filter(e => e !== `${action.element.id}`);

                return {
                    ...newState,
                    elementsMap: {
                        ...newState.elementsMap,
                        [element]: action.element,
                    },
                    visibleElements: [...newVisibleElements, element],
                    unplacedElements: [...newUnplacedElements],
                };
            }

            return {
                ...state,
                elementsMap: {
                    ...state.elementsMap,
                    [action.element.id]: action.element,
                },
                visibleElements: [...state.visibleElements, element],
                unplacedElements: [...state.unplacedElements, unplacedElement],
            };
        default:
            return state;
    }
}

      

As I mentioned earlier, sometimes the update works, but not every time. I've narrowed it down to the client. The server seems to be doing fine. Any idea what I am doing wrong here? Thank!

+3


source to share


1 answer


If you are using takeLatest

, the documentation on the reduction saga mentions:

https://redux-saga.js.org/docs/basics/UsingSagaHelpers.html

Unlike takeEvery, takeLatest allows only one fetchData task to run at any given time. And this will be the last task launched. If the previous task is still running while another fetchData task is running, the previous task will be automatically canceled .

Where fetchData

is the generator function which is supplied with takeLatest

ortakeEvery

And when your UI keeps referencing the same action, before it completes, it will continue to undo the last invoked action, and hence you will keep getting the message intermittently:



updateElementSaga has been cancelled

Which is by nature takeLatest

doing the right thing. What is:

Always take the latest invoked action

If you want every action to be caught and processed, use takeEvery

like:

export default [
    takeEvery('requestUpdateElement', updateElementSaga),
];

      

+4


source







All Articles