From 7de97d82222a61a80b3ea8f86630bab187299bf4 Mon Sep 17 00:00:00 2001 From: xfy Date: Wed, 1 Jul 2026 15:41:05 +0800 Subject: [PATCH] =?UTF-8?q?fix(write):=20=E7=BC=96=E8=BE=91=E6=A8=A1?= =?UTF-8?q?=E5=BC=8F=E5=9B=9E=E6=98=BE=E7=A9=BA=E7=99=BD=E7=94=B1=20effect?= =?UTF-8?q?=20=E7=AB=9E=E6=80=81=E5=AF=BC=E8=87=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 编辑文章时编辑器空白。根因:edit_post 由 None→Some 时,回填 effect (写 content signal)与初始化 effect(读 content signal)在同一 tick 触发,无保证先后顺序。初始化 effect 经常先跑,读到 content()= 跳过 setMarkdown,且 editor_content_set=true 永久阻止重试。 修复:初始化 effect 直接从 edit_post(真值源)取 content_md 回填,不再 依赖 content signal——后者是派生值,与回填 effect 存在竞态。两个 effect 都已在 edit_post 上订阅,回填时读取它没有竞态。 --- src/pages/admin/write.rs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/pages/admin/write.rs b/src/pages/admin/write.rs index 581cec7..5158722 100644 --- a/src/pages/admin/write.rs +++ b/src/pages/admin/write.rs @@ -154,7 +154,11 @@ fn write_editor(post_id: Option) -> Element { // use_effect 在首次渲染后跑,此时 #tiptap-editor 容器已挂载。 #[cfg(target_arch = "wasm32")] use_effect(move || { - // 编辑模式:等数据加载完再初始化(避免空内容覆盖回填) + // 编辑模式:等数据加载完再初始化(避免空内容覆盖回填)。 + // 回填内容直接从 edit_post(唯一可信源)取,不走 content signal—— + // content 由独立的回填 effect 写入,两者在 edit_post 变更同一 tick 触发时 + // 没有保证的先后顺序:本 effect 可能先于回填 effect 跑,读到仍是空串, + // 导致 setMarkdown 被跳过、编辑器空白(且 editor_content_set=true 阻止重试)。 if is_edit && edit_post().is_none() { return; } @@ -193,11 +197,16 @@ fn write_editor(post_id: Option) -> Element { // —— create(同步返回;找不到容器返回 None,构造失败抛异常)—— match crate::tiptap_bridge::get_module().create("tiptap-editor", &opts) { Ok(Some(inst)) => { - // 编辑模式回填:create 成功立即回填(实例已创建,时机确定) + // 编辑模式回填:create 成功立即回填(实例已创建,时机确定)。 + // 直接从 edit_post 取 content_md:本 effect 已在上面 guard 了 edit_post.is_none(), + // 而 edit_post 是异步加载后一次性写入、之后只读的真值源,读取它没有竞态。 + // 用 editor_content_set 防重复回填(effect 重跑时跳过)。 if is_edit && !editor_content_set() { - let md = content(); - if !md.is_empty() { - inst.set_markdown(&md); + if let Some(post) = edit_post() { + let md = &post.content_md; + if !md.is_empty() { + inst.set_markdown(md); + } } editor_content_set.set(true); }