You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Currently using a Firebase Realtime Database as an event emitter/subscription to when certain events are completed (i.e., adding an item to a cart). The first issue I had was that I was calling invalidateQueries within onSettled of the mutation, thus doing a rollback of my optimistic update since the response is 202 with no returned body:
- Click 'Add to Cart' -> mutation with POST to /api/cart/add -> returns 202 and no returned body response
- Optimistically update cart with product [{ id: 1, quantity: 1 }]
- Since mutation is complete, onSettled will invalidate query to [] since cart still updating in Firebase
To prevent this, I instead created a custom hook which will listen to the events and if the event type matched the relevant mutation, I would call invalidateQueries there:
React.useEffect(()=>{constunsubscribe=db.collection('notifications').doc(userId).collection('events').onSnapshot(querySnapshot=>{querySnapshot.docChanges().forEach(change=>{const{ type }=change.doc.data();switch(type){case'cart_updated': {queryClient.invalidateQueries(['cart',{ userId }]);break;}default:
}});},error=>{// log});return()=>unsubscribe();},[db,userId]);
This works when clicking a single 'Add to Cart' button to trigger the mutation. The issue then arises when clicking multiple 'Add to Cart' for different items. Since adding an item to the cart could possibly take some time (let's say 200ms-1500ms), The cart would rollback numerous times since we're getting fresh data via invalidateQueries without those new items added.
Click 'Add to Cart' No.1
Optimistically update cart with product [{ id: 1, quantity: 1 }]
Cart now [{ id: 1, quantity: 1 }]
Click 'Add to Cart' No.2
Optimistically update cart with product [{ id: 2, quantity: 1 }]
Cart now [{ id: 1, quantity: 1 }, { id: 2, quantity: 1 }]
Click 'Add to Cart' No.3
Optimistically update cart with product [{ id: 3, quantity: 1 }]
Cart now [{ id: 1, quantity: 1 }, { id: 2, quantity: 1 }, { id: 3, quantity: 1 }]
// cart_updated received from event subscription for No.1 , invalidate query
Cart now [{ id: 1, quantity: 1 }]
// cart_updated received from event subscription for No.2 , invalidate query
Cart now [{ id: 1, quantity: 1 }, { id: 2, quantity: 1 }]
// cart_updated received from event subscription for No.3 , invalidate query
Cart now [{ id: 1, quantity: 1 }, { id: 2, quantity: 1 }, { id: 3, quantity: 1 }]
Hopefully that explains the situation. Even though this explanation looks more synchronous, at times the events are returned in between adding the items:
Click 'Add to Cart' No.1
Optimistically update cart with product [{ id: 1, quantity: 1 }]
Cart now [{ id: 1, quantity: 1 }]
Click 'Add to Cart' No.2
Optimistically update cart with product [{ id: 2, quantity: 1 }]
Cart now [{ id: 1, quantity: 1 }, { id: 2, quantity: 1 }]
// cart_updated received from event subscription for No.1 , invalidate query
Cart now [{ id: 1, quantity: 1 }]
Click 'Add to Cart' No.3
Optimistically update cart with product [{ id: 3, quantity: 1 }]
Cart now [{ id: 1, quantity: 1 }, { id: 3, quantity: 1 }]
// cart_updated received from event subscription for No.2 , invalidate query
Cart now [{ id: 1, quantity: 1 }, { id: 2, quantity: 1 }]
// cart_updated received from event subscription for No.3 , invalidate query
Cart now [{ id: 1, quantity: 1 }, { id: 2, quantity: 1 }, { id: 3, quantity: 1 }]
As you can see, the cart could appear with missing items and eventually pop up with the true state of the cart from the server.
I was wondering if there was any to batch the mutations or perhaps wait to invalidate the query? My idea was to keep a sort of counter and compare the events returned with said counter before invalidation. So if I clicked 'Add to Cart' 5 times, it's expected that I will indeed get 5 events returned, so wait for 5 THEN invalidate. However this seems clunky.
Anyone got any better ideas? Hopefully my explanation makes sense.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
-
Currently using a Firebase Realtime Database as an event emitter/subscription to when certain events are completed (i.e., adding an item to a cart). The first issue I had was that I was calling
invalidateQueries
withinonSettled
of the mutation, thus doing a rollback of my optimistic update since the response is 202 with no returned body:To prevent this, I instead created a custom hook which will listen to the events and if the event type matched the relevant mutation, I would call
invalidateQueries
there:This works when clicking a single 'Add to Cart' button to trigger the mutation. The issue then arises when clicking multiple 'Add to Cart' for different items. Since adding an item to the cart could possibly take some time (let's say 200ms-1500ms), The cart would rollback numerous times since we're getting fresh data via
invalidateQueries
without those new items added.Hopefully that explains the situation. Even though this explanation looks more synchronous, at times the events are returned in between adding the items:
As you can see, the cart could appear with missing items and eventually pop up with the true state of the cart from the server.
I was wondering if there was any to batch the mutations or perhaps wait to invalidate the query? My idea was to keep a sort of counter and compare the events returned with said counter before invalidation. So if I clicked 'Add to Cart' 5 times, it's expected that I will indeed get 5 events returned, so wait for 5 THEN invalidate. However this seems clunky.
Anyone got any better ideas? Hopefully my explanation makes sense.
Beta Was this translation helpful? Give feedback.
All reactions