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

831 views Asked by At

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?

2

There are 2 answers

1
Jonas Fassbender On BEST ANSWER

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);
}
0
Helbert Gascon On

You can also try passing the struct directly over main by using launch_with_props():

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

    dioxus_desktop::launch_with_props(App, big_struct, Config::new())
}

From there, you should be able to access it in the component thru cx.props.s.