I am trying to get the value of title_state, which is located inside a callback of the main app component.
#[function_component(App)]
fn app() -> Html {
let title_state = use_state(|| String::default());
let title_change_cb = Callback::from(move |v:String| {
let title_state = title_state.clone();
title_state.set(v);
});
html! {
<>
<TitleController callback={title_change_cb}/>
<p>{*title_state}</p>
</>
}
}
The same callback is passed to TitleController.
#[derive(Properties, PartialEq)]
pub struct TitleControllerProps {
pub callback: Callback<String>
}
#[function_component(TitleController)]
pub fn title_controller(props: &TitleControllerProps) -> Html {
let callback = Callback::clone(&props.callback);
let input_nr = use_node_ref();
let onchange = {
let input_nr = input_nr.clone();
Callback::from(move |_:Event| {
let input = input_nr.cast::<HtmlInputElement>();
if let Some(input) = input {
callback.emit(input.value());
}
})
};
html! {
<>
<h1>{"Title Controller"}</h1>
<input ref={input_nr}
{onchange}
id="my-input"
type="text"
/>
</>
}
}
So far i have only tried common solutions like clone(), using immutable references but nothing works.
Errors i get:
With dereference operator only:
error[E0507]: cannot move out of dereference of `UseStateHandle<String>`
--> src/main.rs:18:17
|
15 | / html! {
16 | | <>
17 | | <TitleController callback={title_change_cb}/>
18 | | <p>{*title_state}</p>
| | ^^^^^^^^^^^^ move occurs because value has type `String`, which does not implement the `Copy` trait
19 | | </>
20 | | }
| |_____- value moved due to this method call
|
When cloning dereferenced state:
error[E0382]: borrow of moved value: `title_state`
--> src/main.rs:18:17
|
7 | let title_state = use_state(|| String::default());
| ----------- move occurs because `title_state` has type `UseStateHandle<String>`, which does not implement the `Copy` trait
8 |
9 | let title_change_cb = Callback::from(move |v:String| {
| --------------- value moved into closure here
10 | let title_state = title_state.clone();
| ----------- variable moved due to use in closure
...
18 | <p>{(*title_state).clone()}</p>
| ^^^^^^^^^^^^^^ value borrowed here after move
|
= note: borrow occurs due to deref coercion to `String`
Your second version is almost correct, you just have to clone
the title_state
before you pass it to the closure so you only move the copy into the closure and still have a handle to the state afterwards:
let title_change_cb = Callback::from({
let title_state = title_state.clone(); // <-- clone here
move |v: String| { // <-- don't clone inside of this
title_state.set(v);
}
});