From 5b30f43252aa17352e282a2caf58f2c19d037c8d Mon Sep 17 00:00:00 2001 From: noelorin Date: Sat, 26 Sep 2026 22:54:56 +0800 Subject: [PATCH] fix(web): hydrate-safe danmaku settings init without render localStorage --- .../components/pages/DanmakuSettingsBody.tsx | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/app/web/src/components/pages/DanmakuSettingsBody.tsx b/app/web/src/components/pages/DanmakuSettingsBody.tsx index d729f1b..c1ba8c1 100644 --- a/app/web/src/components/pages/DanmakuSettingsBody.tsx +++ b/app/web/src/components/pages/DanmakuSettingsBody.tsx @@ -80,14 +80,25 @@ function Inner(props: { locale: Locale }) { const save = trpc.media.danmakuSaveSettings.useMutation(); const filledFromServer = useRef(false); - const initial = readSettings(); - const [enabled, setEnabled] = useState(initial.enabled); - const [opacity, setOpacity] = useState(initial.opacity); - const [density, setDensity] = useState(initial.density); - const [blockKeywords, setBlockKeywords] = useState(initial.blockKeywords); - const [blockTypes, setBlockTypes] = useState(initial.blockTypes); + // SSR 与水合首帧共用 FALLBACK,避免 localStorage 差异导致 hydration 不一致 + const [enabled, setEnabled] = useState(FALLBACK.enabled); + const [opacity, setOpacity] = useState(FALLBACK.opacity); + const [density, setDensity] = useState(FALLBACK.density); + const [blockKeywords, setBlockKeywords] = useState(() => []); + const [blockTypes, setBlockTypes] = useState(() => []); const [kwInput, setKwInput] = useState(""); + // 挂载后再读 localStorage 作初值/回退(客户端 only) + useEffect(() => { + const local = readSettings(); + if (filledFromServer.current) return; + setEnabled(local.enabled); + setOpacity(local.opacity); + setDensity(local.density); + setBlockKeywords(local.blockKeywords); + setBlockTypes(local.blockTypes); + }, []); + useEffect(() => { const data = prefsQuery.data; if (!data || filledFromServer.current) return;