我在use_effect中有一个事件侦听器,在那里我想从鼠标事件中获取值并将其设置为状态.要添加我使用的use_node_ref事件侦听器,但我收到下一个错误:

error[E0597]: `coordinates` does not live long enough
  --> src/test.rs:33:17
   |
24 |           |div_ref| {
   |           --------- value captured here
...
29 |               let listener = Closure::<dyn Fn(MouseEvent)>::wrap(Box::new(|event| {
   |  ________________________________________________________________-
30 | |                 let x = event.x();
31 | |                 let y = event.y();
32 | |                 web_sys::console::log_1(&x.into());
33 | |                 coordinates.set(Coordinates { x: x, y: y });
   | |                 ^^^^^^^^^^^ borrowed value does not live long enough
34 | |                 
35 | |             }));
   | |______________- cast requires that `coordinates` is borrowed for `'static`
...
53 |   }
   |   - `coordinates` dropped here while still borrowed

这是一个可重复使用的例子:

use wasm_bindgen::prelude::Closure;
use web_sys::HtmlElement;
use yew::prelude::*;
use wasm_bindgen::JsCast;
use web_sys;
use yew::{function_component, html, use_effect_with_deps, use_node_ref, Html};

struct Coordinates {
    x: i32,
    y: i32,
}

#[function_component]
fn Test() -> Html {
    let div_ref = use_node_ref();
    let coordinates: UseStateHandle<Coordinates> = use_state(|| Coordinates { x: 0, y: 0 });
        

{
    let div_ref = div_ref.clone();
    let coordinates = coordinates.clone();

    use_effect_with_deps(
        |div_ref| {
            let div = div_ref
                .cast::<HtmlElement>()
                .expect("div_ref not attached to div element");

            let listener = Closure::<dyn Fn(MouseEvent)>::wrap(Box::new(|event| {
                let x = event.x();
                let y = event.y();
                web_sys::console::log_1(&x.into());
                coordinates.set(Coordinates { x: x, y: y }); // <- here is the problem
                
            }));

            div.add_event_listener_with_callback(
                "mousemove",
                listener.as_ref().unchecked_ref(),
            )
            .unwrap();

            move || {
                div.remove_event_listener_with_callback(
                    "mousemove",
                    listener.as_ref().unchecked_ref(),
                )
                .unwrap();
            }
        },
        div_ref,
    );
}

    html! {
        <div ref={div_ref}>{"Test"}</div>
    }
}

fn main() {
    yew::Renderer::<Test>::new().render();
}

如何在USE_EFECT_WITH_DEPS中设置监听器内部的状态?

推荐答案

Ruust给出这个错误是因为coordinates当前只在声明它的函数中存在(即,一旦Test结束,coordinates就被删除),但您的闭包必须是'static,这意味着它们超出了Test的作用域(也就是说,即使Test结束,它们也需要有效).

为了避免这个问题,可以使用闭包移动coordinates,方法是在闭包前面添加关键字move.这将使闭包获得coordinates的所有权,这意味着它将不再在Test年末被删除.

Rust相关问答推荐

Tauri tauri—apps/plugin—store + zustand

为什么我需要在这个代码示例中使用&

交叉术语未正确清除屏幕

这个规则关于或模式到底是什么意思?如果表达片段的类型与p_i|q_i...&q;不一致,就会形成

如何使用syn插入 comments ?

如何实现泛型枚举的`Serde::Desialize`特性

替换可变引用中的字符串会泄漏内存吗?

Rust&;Tokio:如何处理更多的信号,而不仅仅是SIGINT,即SIGQUE?

我是否可以在Ruust中修改 struct 实例上的字符串,以使其在修改后具有相同的字符串生存期?

我如何使用AWS SDK for Rust获取我承担的角色的凭据?

循环访问枚举中的不同集合

失真图像图形捕获Api

在Rust内联程序集中使用字符串常量

如何对一个特征的两个实现进行单元测试?

我可以解构self 参数吗?

将泛型中的 Box 转换为 rust 中的 Box

Rust:`sort_by` 多个条件,冗长的模式匹配

如果不满足条件,如何在 Rust 中引发错误

在 Rust 中,将可变引用传递给函数的机制是什么?

如何从 Rust 函数返回数组而不复制它们?