Redux updateElementSaga已被取消.为什么?

Zac*_*iro 3 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 };
}
Run Code Online (Sandbox Code Playgroud)

在我的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),
];
Run Code Online (Sandbox Code Playgroud)

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');
    }
}
Run Code Online (Sandbox Code Playgroud)

我的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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

Nag*_*tri 6

如果您使用的takeLatest是redux saga文档确实提到:

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

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

fetchData使用takeLatest或提供的生成器函数在哪里?takeEvery

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

updateElementSaga has been cancelled

这本质上takeLatest是正确的做法.这是:

Always take the latest invoked action

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

export default [
    takeEvery('requestUpdateElement', updateElementSaga),
];
Run Code Online (Sandbox Code Playgroud)