I am using same form and same state in redux for add and edit. When I call api for fetching data for edit and we change our router to add form before the response arrives. All the form datas will be auto filled for add item since i am using same state for both add and edit. Is there any way to prevent this from happening?
my action creator:
fetchById: function (entity, id) {
return function (dispatch) {
dispatch(apiActions.apiRequest(entity));
return (apiUtil.fetchById(entity, id).then(function (response) {
dispatch(apiActions.apiResponse(entity));
dispatch(actions.selectItem(entity, response.body));
}
}
}
As response is late then selectItem is dispatched late. And when I open form for adding item then this form is filled with this data from response.
Thunks get both dispatch
and getState
as arguments.
If you keep the current route somewhere in your state, you can check in the API callback whether you’re still on the same page with getState().routing.path
or something like this, and return
if it has changed since the API call started.
If you don’t keep the current route in the state, you can instead read this.context.router
in your component (don’t forget to define contextTypes
to get it!) and pass it to the action creator. The action creator can then use router.isActive()
to check whether we’re still on the same path before and after the request.
Finally, you can just not use the same state for editing and adding an item. Your state shape can look like { drafts: { newItem: ..., 1: ..., 2: ... } }
and you could keep the “add” form in drafts.newItem
, and keep any “edit” form by the corresponding entity’s ID. This way they would never overwrite each other and, as a bonus, in-progress edits could be preserved, e.g. if you press “Back” and then go to the form again (depending on whether you want this in your UX of course).
I saw this blog post the other day and I think the second part describes what you are looking for. You don't necessarily want to cancel the requests but ignore the responses.
Basically you want to create an outer reducer which will keep track of your async requests to the server with unique ids. Only if the request id is in the list then allow it into the sub reducers.
When you switch page you will want to clear out this list of unique ids.
Lifted straight from the blog:
const initialState = [];
function update(state = initialState, action) {
const { seqId } = action;
if (action.type === constants.UNLOAD) {
return initialState;
}
else if (seqId) {
let newState;
if (action.status === 'start') {
newState = [...state, seqId];
}
else if (action.status === 'error' || action.status === 'done') {
newState = state.filter(id => id !== seqId);
}
return newState;
}
return state;
}
and then restrict the sub reducers:
let store = createStore((state, action) => {
if (action.seqId &&
(action.status === 'done' || action.status === 'error') &&
state &&
state.asyncRequests.indexOf(action.seqId) === -1) {
return state;
}
return reducer(state, action);
});
Big shout out to James for this. Really nice solution and very well explained in his blog post.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With