Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Beginner confusion: Docs fix? Can't call methods inside rsx! { ... } ? #3073

Open
tgrushka opened this issue Oct 18, 2024 · 2 comments
Open

Comments

@tgrushka
Copy link

(Is it a) Problem (/ Rust limitation?)

The following works (awesome!):

#[derive(Clone, strum::EnumIter, Routable, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
enum Route {
    #[route("/")]
    Home {},
    #[route("/counter")]
    Counter {},
    #[route("/blog/:id")]
    Blog { id: i32 },
}

impl Route {
    fn icon(&self) -> String {
        match self {
            Route::Home {} => "home".into(),
            Route::Counter {} => "add_circle".into(),
            Route::Blog { .. } => "blog".into(),
        }
    }

    fn title(&self) -> String {
        match self {
            Route::Home {} => "Home".into(),
            Route::Counter {} => "Counter".into(),
            Route::Blog { .. } => "Blog".into(),
        }
    }
}

#[component]
fn RailDrawerNav() -> Element {
    let nav_buttons = Route::iter().map(|route| {
        let icon = route.icon();
        let title = route.title();
        rsx! {
          Link { to: route,
            i { "{icon}" }
            div { "{title}" }
          }
        }
    });
    rsx! {
      nav { class: "left drawer l",
        header {
          nav {
            img {
              src: "https://www.beercss.com/favicon.png",
              class: "circle"
            }
            h6 { "Cheers" }
          }
        }
        for button in nav_buttons {
          { button }
        }
        div { class: "divider" }
        a {
          i { "search" }
          div { "Search" }
        }
        a {
          i { "share" }
          div { "Share" }
        }
        a {
          i { "more_vert" }
          div { "More" }
        }
      }
    }
}


#[component]
fn Blog(id: i32) -> Element {
    rsx! {
      RailDrawerNav {}
      // ...
    }
}

But the following does not work (why does the analyzer show an irrelevant missing trailing comma error?):

#[component]
fn RailDrawerNav() -> Element {
    rsx! {
      nav { class: "left drawer l",
        header {
          nav {
            img {
              src: "https://www.beercss.com/favicon.png",
              class: "circle"
            }
            h6 { "Cheers" }
          }
        }
        for route in Route::iter() {
          Link { to: route,
            i { route.icon() } // missing trailing comma rust-analyzer[macro-error]
            div { route.title() }
          }
        }
        // ...
      }
      // ...
    }
}

Was hoping to do that, but then it became only slightly clearer when I found this compiles, but yields improper output because it's interpreting icon and title as attribute keys, not values:

let nav_buttons = Route::iter().map(|route| {
    let icon = route.icon();
    let title = route.title();
    rsx! {
      Link { to: route,
        i { icon }
        div { title }
      }
    }
});

Steps To Reproduce

Try the above code snippets.

Expected behavior

It is likely expected. However, it would be helpful to have:

  1. Better tutorial docs on dealing with things like properties / methods of things. If I had a say, this would be a high priority as it should be an easy fix for the maintainers knowing how it should work. Just a quick example section would be great, because it's probably a very common stumbling block for newcomers.
  2. A better analyzer error (not trailing comma) -- I saw another issue that suggests this might be in the works but don't know if related. Probably much harder fix, knowing Rust macro analyzer limitations.

Screenshots

Unwanted render trying the last method above (unquoted var name as node content, i.e. div { title }):
image

Correct render with quoted var names, i.e. div { "{title}" }
image

Environment:

  • Dioxus version: 0.5.7 -->
  • Rust version: rustc 1.82.0 (f6e511eec 2024-10-15) stable -->
  • OS info: macOS 15.0.1
  • App platform: fullstack hot-reload

Questionnaire

I would like to help fix this by helping with documentation but I'm brand new to this framework so I'm not sure of the recommended way to deal with this issue. If I knew, would be happy to write up a PR for the docs.

@tgrushka
Copy link
Author

tgrushka commented Oct 18, 2024

Wait 2 milliseconds!

I think I found it (wrap method calls in extra { ... }:

#[component]
fn RailDrawerNav() -> Element {
    rsx! {
      nav { class: "left drawer l",
        header {
          nav {
            img {
              src: "https://www.beercss.com/favicon.png",
              class: "circle"
            }
            h6 { "Cheers" }
          }
        }
        for route in Route::iter() {
          Link { to: route.clone(),
            i { { route.icon() } }
            div { { route.title() } }
          }
        }
// ...

Would be happy to contribute a docs PR.

@ealmloff
Copy link
Member

ealmloff commented Oct 21, 2024

Dioxus rsx is similar to rust structs, if you have a plain ident with the name of an attribute, then it set the attribute (like Foo { bar } sets the fieled bar to the value bar). This is documented here:

  1. In the rsx reference: https://dioxuslabs.com/learn/0.5/reference/rsx#expressions
  2. In the (new 0.6 only) rsx inline docs: https://docs.rs/dioxus/0.6.0-alpha.3/dioxus/prelude/macro.rsx.html#raw-expressions
  3. In the (new 0.6 only) examples alongside element: https://docs.rs/dioxus-html/0.6.0-alpha.3/dioxus_html/elements/div/index.html#usage-in-rsx

I think we can improve the macro error message for that parsing case. It would be helpful to hear what documentation you have read before running into this issue so that we know where cross links need to be added. There are some plans to expand the guide in DioxusLabs/docsite#277

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants