我刚刚使用react-dnd实现了一个拖放功能,当用户在我的应用中删除SkyElement
项时,我会在服务器上更新top
和left
更新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;
}
}
就像我之前提到的,有时更新有效,但不是每次都有效。我已将问题缩小到客户端。服务器似乎行事正常。知道我在这里做错了什么吗?谢谢!
答案 0 :(得分: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),
];