fix(client): wrap connect/disconnect in untrack() to break effect loop
Svelte 5 $effect tracks every $state read inside its body. The lifecycle effect that calls game.connect(gameId) implicitly read state.ws (inside connect()) and then wrote to it, producing an effect_update_depth_exceeded loop. Symptom in production: the browser opened ~12 WS connections/sec, none completed the upgrade handshake, and the lobby flow appeared stuck on 'waiting for opponent' (the opponent's WS never stabilized long enough for the server to send 'joined'). untrack() opts the call out of dep tracking. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { untrack } from 'svelte';
|
||||||
import { game } from './stores/game.svelte.js';
|
import { game } from './stores/game.svelte.js';
|
||||||
import Board from './Board.svelte';
|
import Board from './Board.svelte';
|
||||||
import ModeratorPanel from './ModeratorPanel.svelte';
|
import ModeratorPanel from './ModeratorPanel.svelte';
|
||||||
@@ -11,9 +12,14 @@
|
|||||||
let armedSquare: Square | null = $state(null);
|
let armedSquare: Square | null = $state(null);
|
||||||
let pendingPromotion: { from: Square; to: Square } | null = $state(null);
|
let pendingPromotion: { from: Square; to: Square } | null = $state(null);
|
||||||
|
|
||||||
|
// Lifecycle effect: connect once when gameId becomes known, disconnect on
|
||||||
|
// teardown. untrack() prevents the connect/disconnect call from registering
|
||||||
|
// any state reads as effect dependencies — without it, reading state.ws
|
||||||
|
// inside connect() triggers Svelte's effect_update_depth_exceeded loop.
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
game.connect(gameId);
|
const id = gameId;
|
||||||
return () => game.disconnect();
|
untrack(() => game.connect(id));
|
||||||
|
return () => untrack(() => game.disconnect());
|
||||||
});
|
});
|
||||||
|
|
||||||
// Once the server commits, our local arm clears (visual state slaved to server).
|
// Once the server commits, our local arm clears (visual state slaved to server).
|
||||||
|
|||||||
Reference in New Issue
Block a user