Skip to content

Commit f937003

Browse files
committed
Send a "reconnect" hydrate whenever the socket reconnects
* "reconnect" hydrate doesn't reset client storage or trigger on_load, it just returns the latest complete state dict * this event is driven by the frontend after the socket connects * update `link_token_to_sid` to NOT emit a delta when the sid changes for a token; the client will be informed of this during the initial hydrate or "reconnect" hydrate. Fix #5963
1 parent 3c3ddc2 commit f937003

File tree

3 files changed

+23
-6
lines changed

3 files changed

+23
-6
lines changed

reflex/.templates/web/utils/state.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,7 @@ export const connect = async (
568568
!socket.current.wait_connect
569569
) {
570570
socket.current.wait_connect = true;
571+
socket.current.rehydrate = true;
571572
socket.current.io.opts.query = { token: getToken() }; // Update token for reconnect.
572573
socket.current.connect();
573574
}
@@ -615,6 +616,19 @@ export const connect = async (
615616
window.addEventListener("pagehide", pagehideHandler);
616617
window.addEventListener("beforeunload", disconnectTrigger);
617618
window.addEventListener("unload", disconnectTrigger);
619+
if (socket.current.rehydrate) {
620+
socket.current.rehydrate = false;
621+
// On reconnect, we only hydrate, do not re-run on_load events.
622+
const hydrate_event = initialEvents()[0];
623+
hydrate_event.payload.is_reconnect = true;
624+
queueEvents(
625+
[hydrate_event],
626+
socket,
627+
true,
628+
navigate,
629+
() => params.current,
630+
);
631+
}
618632
// Drain any initial events from the queue.
619633
while (event_queue.length > 0 && !event_processing) {
620634
await processEvent(socket.current, navigate, () => params.current);

reflex/app.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2263,7 +2263,7 @@ async def link_token_to_sid(self, sid: str, token: str):
22632263
await self.emit("new_token", new_token, to=sid)
22642264

22652265
# Update client state to apply new sid/token for running background tasks.
2266-
async with self.app.modify_state(
2266+
async with self.app.state_manager.modify_state(
22672267
_substate_key(new_token or token, self.app.state_manager.state)
22682268
) as state:
22692269
state.router_data[constants.RouteVar.SESSION_ID] = sid

reflex/middleware/hydrate_middleware.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,14 @@ async def preprocess(
3535
if event.name != get_hydrate_event(state):
3636
return None
3737

38-
# Clear client storage, to respect clearing cookies
39-
state._reset_client_storage()
40-
41-
# Mark state as not hydrated (until on_loads are complete)
42-
setattr(state, constants.CompileVars.IS_HYDRATED, False)
38+
# In reconnect mode, don't reset client storage or call on_load.
39+
is_reconnect = event.payload.get("is_reconnect", False)
40+
if not is_reconnect:
41+
# Clear client storage, to respect clearing cookies
42+
state._reset_client_storage()
43+
44+
# Mark state as not hydrated (until on_loads are complete)
45+
setattr(state, constants.CompileVars.IS_HYDRATED, False)
4346

4447
# Get the initial state.
4548
delta = await _resolve_delta(state.dict())

0 commit comments

Comments
 (0)