fix(code_runner): use_resolved_theme 从 use_effect 闭包提到 cfg 块顶层
dx check 报 4 处 'hook called in a closure: use_resolved_theme':
use_resolved_theme() 是 hook(内部 use_context),被错误地放在 use_effect 的
move || { ... } 闭包内调用。Dioxus 规则要求 hook 只能在组件渲染路径顶层调用。
修复:在两个 #[cfg(target_arch="wasm32")] 块顶层各调用一次 use_resolved_theme()
拿到 Memo<ResolvedTheme>,move 进下方 effect 闭包;闭包内改为调用 memo
(resolved_theme())读值。调用 memo 本身不是 hook(Memo 是 Copy + Fn),
读值的同时建立主题订阅——主题切换时 effect 仍会重跑,行为不变。
范式对齐 ThemeToggle(src/theme.rs:341)的正确用法。
影响 4 处:CodeMirror 挂载/主题同步 effect、xterm 挂载/主题同步 effect。
This commit is contained in:
parent
0b40105341
commit
50e64cd34c
@ -126,6 +126,10 @@ pub fn CodeRunner(
|
|||||||
|
|
||||||
let mut editor_handle: Signal<Option<codemirror_bridge::EditorHandle>> =
|
let mut editor_handle: Signal<Option<codemirror_bridge::EditorHandle>> =
|
||||||
use_signal(|| None);
|
use_signal(|| None);
|
||||||
|
// 在 cfg 块顶层(渲染路径)取主题 memo,move 进下方 effect 闭包;闭包内只
|
||||||
|
// 调用 memo(resolved())读值——调用 memo 本身不是 hook,use_resolved_theme
|
||||||
|
// 这个 hook 必须在组件体顶层调用,不能放进 use_effect 闭包(dx check 会报)。
|
||||||
|
let resolved_theme = use_resolved_theme();
|
||||||
|
|
||||||
// 首次挂载:构造 closure + options,create 后存进 editor_handle。
|
// 首次挂载:构造 closure + options,create 后存进 editor_handle。
|
||||||
// 用 resolved() 读取主题作为初始值(同时订阅,但主题切换由下方独立 effect 处理)。
|
// 用 resolved() 读取主题作为初始值(同时订阅,但主题切换由下方独立 effect 处理)。
|
||||||
@ -146,8 +150,7 @@ pub fn CodeRunner(
|
|||||||
// 但 EditorHandle 签名要求该闭包,传 no-op 满足生命周期。
|
// 但 EditorHandle 签名要求该闭包,传 no-op 满足生命周期。
|
||||||
let on_run_shortcut = Closure::new(|| {});
|
let on_run_shortcut = Closure::new(|| {});
|
||||||
|
|
||||||
let resolved = use_resolved_theme();
|
let theme_name = if resolved_theme() == ResolvedTheme::Dark {
|
||||||
let theme_name = if resolved() == ResolvedTheme::Dark {
|
|
||||||
"dark"
|
"dark"
|
||||||
} else {
|
} else {
|
||||||
"light"
|
"light"
|
||||||
@ -186,7 +189,6 @@ pub fn CodeRunner(
|
|||||||
// 期间跳过,让 VT 事件负责换肤;动画结束后此 effect 会因 resolved 信号变化重跑
|
// 期间跳过,让 VT 事件负责换肤;动画结束后此 effect 会因 resolved 信号变化重跑
|
||||||
// (此时 is-theme-transitioning 已移除),做一次幂等的兜底同步。
|
// (此时 is-theme-transitioning 已移除),做一次幂等的兜底同步。
|
||||||
use_effect(move || {
|
use_effect(move || {
|
||||||
let r = use_resolved_theme();
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
{
|
{
|
||||||
let transitioning = web_sys::window()
|
let transitioning = web_sys::window()
|
||||||
@ -200,7 +202,7 @@ pub fn CodeRunner(
|
|||||||
}
|
}
|
||||||
if let Some(h) = editor_handle.read().as_ref() {
|
if let Some(h) = editor_handle.read().as_ref() {
|
||||||
h.instance()
|
h.instance()
|
||||||
.set_theme(if r() == ResolvedTheme::Dark {
|
.set_theme(if resolved_theme() == ResolvedTheme::Dark {
|
||||||
"dark"
|
"dark"
|
||||||
} else {
|
} else {
|
||||||
"light"
|
"light"
|
||||||
@ -242,6 +244,10 @@ pub fn CodeRunner(
|
|||||||
use crate::xterm_bridge;
|
use crate::xterm_bridge;
|
||||||
use wasm_bindgen::closure::Closure;
|
use wasm_bindgen::closure::Closure;
|
||||||
|
|
||||||
|
// 在 cfg 块顶层(渲染路径)取主题 memo,move 进下方 effect 闭包;闭包内只
|
||||||
|
// 调用 memo(resolved_theme())读值——调用 memo 本身不是 hook。
|
||||||
|
let resolved_theme = use_resolved_theme();
|
||||||
|
|
||||||
// 首次挂载:构造 onReady 闭包 + XtermOptions,create 后存进 term_handle。
|
// 首次挂载:构造 onReady 闭包 + XtermOptions,create 后存进 term_handle。
|
||||||
// 订阅 show_output:输出区在 show_output 变 true(用户点运行)后才渲染进 DOM,
|
// 订阅 show_output:输出区在 show_output 变 true(用户点运行)后才渲染进 DOM,
|
||||||
// 容器此前不存在;读 show_output 建立订阅,使其变 true 时重跑本 effect 完成挂载。
|
// 容器此前不存在;读 show_output 建立订阅,使其变 true 时重跑本 effect 完成挂载。
|
||||||
@ -255,8 +261,7 @@ pub fn CodeRunner(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let on_ready = Closure::new(|| {});
|
let on_ready = Closure::new(|| {});
|
||||||
let resolved = use_resolved_theme();
|
let theme_name = if resolved_theme() == ResolvedTheme::Dark {
|
||||||
let theme_name = if resolved() == ResolvedTheme::Dark {
|
|
||||||
"dark"
|
"dark"
|
||||||
} else {
|
} else {
|
||||||
"light"
|
"light"
|
||||||
@ -278,7 +283,6 @@ pub fn CodeRunner(
|
|||||||
// 主题切换时同步终端主题。
|
// 主题切换时同步终端主题。
|
||||||
// VT 动画期间跳过(同 CodeMirror 的 use_effect,见上方注释)。
|
// VT 动画期间跳过(同 CodeMirror 的 use_effect,见上方注释)。
|
||||||
use_effect(move || {
|
use_effect(move || {
|
||||||
let r = use_resolved_theme();
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
{
|
{
|
||||||
let transitioning = web_sys::window()
|
let transitioning = web_sys::window()
|
||||||
@ -292,7 +296,7 @@ pub fn CodeRunner(
|
|||||||
}
|
}
|
||||||
if let Some(h) = term_handle.read().as_ref() {
|
if let Some(h) = term_handle.read().as_ref() {
|
||||||
h.instance()
|
h.instance()
|
||||||
.set_theme(if r() == ResolvedTheme::Dark {
|
.set_theme(if resolved_theme() == ResolvedTheme::Dark {
|
||||||
"dark"
|
"dark"
|
||||||
} else {
|
} else {
|
||||||
"light"
|
"light"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user