I want to save state
into my database whenever any of its properties changes. I currently have two middlewares that would dispatch
my saveTrip function.
The two middlewares are identical but listen to different actionCreators.
Store.js:
listenerMiddleWare.startListening({
actionCreator: setOrigin,
effect: async(action, listenerAPI) => {
listenerAPI.cancelActiveListeners();
// await listenerAPI.delay(1000)
console.log("side effect origin");
listenerAPI.dispatch(saveTrip(action.payload))
}
})
listenerMiddleWare.startListening({
actionCreator: setDestination,
effect: async(action, listenerAPI) => {
listenerAPI.cancelActiveListeners();
// await listenerAPI.delay(1000)
console.log("side effect destination");
listenerAPI.dispatch(saveTrip(action.payload))
}
})
Savetrip function:
export const saveTrip = createAsyncThunk(
'trip/saveTrip',
debounce(async (payload, thunkAPI) => {
const trip = thunkAPI.getState().trip
try {
fetch(
'http://localhost:5000/savetrip', {
mode: 'cors',
credentials: 'include',
method: "post",
body: JSON.stringify({trip}),
headers: {
'Content-Type': 'application/json'
},
})
.then(res => res.json())
.then(response => {
console.log(response)
thunkAPI.dispatch(setMongoID(response))
})
} catch (error) {
console.log(error);
}
}, 2000)
)
I am not even using the payload thats passed in when I call saveTrip
as I’m saving the entries state
. I don’t have any bugs, but my code seems redundant if I need more listeners. Is there a better approach to this? I basically want to save my state into DB whenever the state changes.
Advertisement
Answer
You can use matchers
listenerMiddleWare.startListening({
matcher: isAnyOf(setOrigin, setDestination),
effect: async(action, listenerAPI) => {
listenerAPI.cancelActiveListeners();
// await listenerAPI.delay(1000)
console.log("side effect origin");
listenerAPI.dispatch(saveTrip(action.payload))
}
})
That said, you are using createAsyncThunk
very wrong – your thunk will finish before the request is even made to the server, long before a response arrives. And you don’t need to dispatch
something in the end, just return
it. Thunks automatically dispatch a .fulfilled
action.
Also, that debouncing will lead to very weird effects. You need to do that on another level, preferrably outside your dispatch
.
export const saveTrip = createAsyncThunk(
'trip/saveTrip',
async (payload, thunkAPI) => {
const trip = thunkAPI.getState().trip
try {
const result = await fetch(
'http://localhost:5000/savetrip', {
mode: 'cors',
credentials: 'include',
method: "post",
body: JSON.stringify({trip}),
headers: {
'Content-Type': 'application/json'
},
})
const response = await result.json()
return response
} catch (error) {
console.log(error);
}
}
)
// then use `saveTrip.fulfilled` in your matcher.