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.