Browse Source

state.js: accumulate incoming events (#1313)

If the backend yields multiple events from a single event handler, ensure that
each event gets appended to the pending result before being transferred to the
state. Previously each incoming event would overwrite any other pending
event(s) leading to racy and unpredictable behavior when yielding events from
the backend in quick succession.

Fixes #1309

Bonus Fix: when setting `processing: false` after client-side events (like
_console), spread from `result`, not `state` to avoid accumulating duplicate
queued events. I think this was originally an undiscovered bug that was exposed
by the main fix.
Masen Furer 1 year ago
parent
commit
5cbf7da952
1 changed files with 4 additions and 4 deletions
  1. 4 4
      reflex/.templates/web/utils/state.js

+ 4 - 4
reflex/.templates/web/utils/state.js

@@ -234,7 +234,7 @@ export const processEvent = async (
 
   // If no event was sent, set processing to false.
   if (!eventSent) {
-    setResult({ ...state, final: true, processing: false });
+    setResult({ ...result, final: true, processing: false });
   }
 };
 
@@ -281,12 +281,12 @@ export const connect = async (
   socket.current.on("event", update => {
     update = JSON5.parse(update);
     applyDelta(state, update.delta);
-    setResult({
+    setResult(result => ({
       state: state,
-      events: update.events,
+      events: [...result.events, ...update.events],
       final: update.final,
       processing: true,
-    });
+    }));
   });
 };