fix: resolve Svelte 5 effect_update_depth_exceeded infinite loop

- ScoreBoard: wrap floats mutation in untrack() to prevent $effect
  from re-triggering when it reads+writes floats in same cycle
- App: split bestScore effect and use untrack() to prevent read/write
  loop on bestScore within the same $effect
This commit is contained in:
2026-04-14 10:25:40 +07:00
parent 5da48bec47
commit 8908881a8d
2 changed files with 14 additions and 3 deletions
+8 -2
View File
@@ -2,6 +2,7 @@
import Grid from './components/Grid.svelte';
import ScoreBoard from './components/ScoreBoard.svelte';
import GameMessage from './components/GameMessage.svelte';
import { untrack } from 'svelte';
import { initGame, move, isGameOver } from './lib/game-logic.js';
import { GRID_SIZE } from './lib/constants.js';
import { getDirectionFromKey, getDirectionFromSwipe } from './lib/input-handler.js';
@@ -27,9 +28,14 @@
});
$effect(() => {
if (gameState.score > bestScore) {
bestScore = gameState.score;
const score = gameState.score;
const best = untrack(() => bestScore);
if (score > best) {
bestScore = score;
}
});
$effect(() => {
saveBestScore(bestScore);
});
+6 -1
View File
@@ -1,4 +1,6 @@
<script>
import { untrack } from 'svelte';
let { score = 0, bestScore = 0, scoreDelta = 0 } = $props();
let floats = $state([]);
@@ -7,7 +9,10 @@
$effect(() => {
if (scoreDelta > 0) {
const id = ++floatId;
floats = [...floats, { id, value: scoreDelta }];
const delta = scoreDelta;
untrack(() => {
floats = [...floats, { id, value: delta }];
});
setTimeout(() => {
floats = floats.filter(f => f.id !== id);
}, 600);