Redux updateElementSaga已被取消。为什么呢?

时间:2017-07-19 19:58:26

标签: javascript reactjs redux react-redux

我刚刚使用react-dnd实现了一个拖放功能,当用户在我的应用中删除SkyElement项时,我会在服务器上更新topleft更新redux商店

但是,更新通话偶尔会有效,而不是每次都有效。在我的控制台中,我看到了警告; updateElementSaga has been cancelled

在我的SlotView.js中,在一个函数中,我有:

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

在我的elements/actions.js

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

在我的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),
];

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');
    }
}

我的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;
    }
}

就像我之前提到的,有时更新有效,但不是每次都有效。我已将问题缩小到客户端。服务器似乎行事正常。知道我在这里做错了什么吗?谢谢!

1 个答案:

答案 0 :(得分:6)

如果你使用的是takeLatest,那么redux saga文档确实提到了:

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

  

与takeEvery不同, takeLatest 只允许运行一个fetchData任务   任何时候。这将是最新开始的任务。如果是以前的   当另一个fetchData任务启动时,任务仍在运行,   上一个任务将自动取消

其中fetchData是使用takeLatesttakeEvery

投放的生成器函数

当你的UI继续调用相同的动作时,在它完成之前,它将继续取消 最后一次调用的动作,因此你会间歇地收到消息:

updateElementSaga has been cancelled

天生takeLatest正在做正确的事。这是:

  

Always take the latest invoked action

如果您希望捕获并处理每个操作,请使用takeEvery,如下:

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