I simply want to pass a function to one of my children through their props so it can be used there.
Here's the code I have now
use log::info;
use yew::html::onclick::Event;
use yew::prelude::*;
// Create Properties with the function I want to use
#[derive(yew::Properties, PartialEq)]
pub struct MyProps {
pub do_this: fn(Event) -> (),
pub val: String,
}
#[function_component(Base)]
pub fn home(props: &MyProps) -> Html {
let do_this_func = props.do_this.clone();
html! {
<button onclick={move |e: Event| do_this_func(e)}> {"press me"} </button>
}
}
// Pass the function
#[function_component(App)]
pub fn app() -> Html {
fn do_this_func(s: Event) {
info!("clicked from my func")
}
html! {
<Base do_this={do_this_func} val={"hello".to_string()} />
}
}
fn main() {
wasm_logger::init(wasm_logger::Config::default());
yew::start_app::<App>();
}
If I remove do_this
and just pass in val
the compiler errors go away. I'd expect that just specifying the type on the props would be enough, but it's not.
Here are the compiler errors I get.
Compiling yew-app v0.1.0 (/Users/sasacocic/development/tinkering/yew-app)
error[E0277]: the trait bound `fn(MouseEvent) {do_this_func}: IntoPropValue<fn(MouseEvent)>` is not satisfied
--> src/main.rs:25:24
|
25 | <Base do_this={do_this_func} val={"hello".to_string()} />
| ------- ^^^^^^^^^^^^ the trait `IntoPropValue<fn(MouseEvent)>` is not implemented for `fn(MouseEvent) {do_this_func}`
| |
| required by a bound introduced by this call
|
= help: the following other types implement trait `IntoPropValue<T>`:
<&'static str as IntoPropValue<AttrValue>>
<&'static str as IntoPropValue<Classes>>
<&'static str as IntoPropValue<Option<AttrValue>>>
<&'static str as IntoPropValue<Option<String>>>
<&'static str as IntoPropValue<String>>
<&T as IntoPropValue<Option<T>>>
<&T as IntoPropValue<T>>
<Classes as IntoPropValue<AttrValue>>
and 6 others
note: required by a bound in `MyPropsBuilder::<MyPropsBuilderStep_missing_required_prop_do_this>::do_this`
--> src/main.rs:5:10
|
5 | #[derive(yew::Properties, PartialEq)]
| ^^^^^^^^^^^^^^^ required by this bound in `MyPropsBuilder::<MyPropsBuilderStep_missing_required_prop_do_this>::do_this`
6 | pub struct MyProps {
7 | pub do_this: fn(Event) -> (),
| ------- required by a bound in this
= note: this error originates in the derive macro `yew::Properties` (in Nightly builds, run with -Z macro-backtrace for more info)
I could implement the IntoPropValue
trait, but that seems a bit extra for just passing a function to child. Is there an simpler way to do this?
A simple solution is to use yew's Callback
. Here's how you can do it with the above example.
The code does a few things differently from the above
use yew::Callback
fn(Event) -> ()
in MyProps
to Callback<Event>
Callback
by doing Callback::from(do_this_func)
emit
i.e. do_this_func.emit(e)
the complete code for this is below and commented
use log::info;
use yew::html::onclick::Event;
use yew::prelude::*;
use yew::Callback; // import Callback
#[derive(yew::Properties, PartialEq)]
pub struct MyProps {
pub do_this: Callback<Event>, // change fn(Event) -> () to Callback<Event>
pub val: String,
}
#[function_component(Base)]
pub fn home(props: &MyProps) -> Html {
let do_this_func = props.do_this.clone();
html! {
// calls the emit method on the Callback
<button onclick={move |e: Event| do_this_func.emit(e)}> {"press me"} </button>
}
}
#[function_component(App)]
pub fn app() -> Html {
fn do_this_func(s: Event) {
info!("clicked from my func")
}
// creates the callback with Callback::from
let cb = Callback::from(do_this_func);
html! {
<Base do_this={cb} val={"hello".to_string()} />
}
}
fn main() {
wasm_logger::init(wasm_logger::Config::default());
yew::start_app::<App>();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With