rustdioxus

Is there a way to pass a prop to the main component in dioxus?


I recently started writing UIs in dioxus and have a big struct that is passed to different components. I do not have full control over that struct as it is from a third-party library. This struct cannot cannot be const and can therefore not be global. It has to be initiated in main. A simplified example might look like this:

use dioxus::prelude::*;

#[derive(Props)]
struct BigStructWrapper<'a> {
    s: &'a mut BigStruct,
}

#[allow(non_snake_case)]
fn App<'a>(cx: Scope<'a, BigStructWrapper<'a>>) -> Element {
    cx.render(rsx! {
        div {
            // Something with BigStructWrapper/BigStruct
        }
    })
}

fn main() {
    let big_struct = BigStructWrapper {
        s: &mut BigStruct::new(),
    };

    dioxus_desktop::launch(App);
}

I then get the error:

error[E0308]: mismatched types
  --> src/main.rs:40:28
   |
31 |     dioxus_desktop::launch(App);
   |     ---------------------- ^^^ expected fn pointer, found fn item
   |     |
   |     arguments to this function are incorrect
   |
   = note: expected fn pointer `for<'a> fn(&'a Scoped<'a>) -> Option<VNode<'a>>`
                 found fn item `for<'a> fn(&'a Scoped<'a, BigStructWrapper<'a>>) -> Option<VNode<'a>> {

Is there a workaround to allow this? Is there a more proper way to do this without a wrapper struct?


Solution

  • I think what you are looking for is described in the Sharing State section of the dioxus documentation. You handle state in dioxus with functions such as use_state or use_ref. Here a small example with use_state where we create the BigStruct instance in our App and pass it down to other components:

    #![allow(non_snake_case)]
    
    use dioxus::prelude::*;
    
    #[derive(Debug, PartialEq)]
    struct BigStruct;
    
    impl BigStruct {
        fn new() -> Self {
            Self
        }
    }
    
    fn App(cx: Scope) -> Element {
        let big_struct = use_state(cx, || BigStruct::new());
    
        cx.render(rsx! {
            Element { bs: big_struct }
        })
    }
    
    #[inline_props]
    fn Element<'a>(cx: Scope, bs: &'a BigStruct) -> Element {
        cx.render(rsx! {
          div {
            "hello {bs:?}"
          }
        })
    }
    
    fn main() {
        dioxus_desktop::launch(App);
    }