leptos icon indicating copy to clipboard operation
leptos copied to clipboard

<Show> vs. <div class "hidden"> rerendering

Open qknight opened this issue 1 year ago • 3 comments

Describe the bug Using <Show ...> ... </Show> from leptos leads to re-rendering vs. using <div class = Some("hidden"). The rerendering is bad as it collapses all my 'manually expanded' info boxes and resets a radio selector to "no" selection.

It took me a few hours to figure out why the elements had collapsed when signal based updates occured.

I encountered this problem when going from the div with hidden to using <Show>:

41bd190e6f7761d975f73647f587edba13afb390

Here is an example of my rewrite:

<div
          id = PageSection::DataCollection.section_id()
          class = move || {
            if current_section.get() == Some(PageSection::DataCollection) || current_section.get() == None {
                None
            } else {
                Some("hidden")
            }
          }
        >

into

<Show when= move || current_section.get() == Some(PageSection::DataCollection)>
        <div id = PageSection::DataCollection.section_id()>
          { set_views.clone() } // input fields for data collection
        </div>

Note: I'm doing client side rendering using WASM in browser.

Leptos Dependencies

Please copy and paste the Leptos dependencies and features from your Cargo.toml.

For example:

leptos = { version = "0.6.5"}

To Reproduce If you want an example I'll build one of course.

Expected behavior I'm not sure.

  • Maybe we should add a notice to https://docs.rs/leptos/latest/leptos/fn.Show.html that rerendering occures.
  • Maybe the <Show implementation is wrong and needs fixing.

I'm curious what others think of this.

qknight avatar Feb 12 '24 12:02 qknight

That is the expected behavior of <Show/>, yes. It's described more explicitly in the description in the book.

The Show component is extremely straightforward: here's the complete body of the function

    let memoized_when = create_memo(move |_| when());

    move || match memoized_when.get() {
        true => children().into_view(),
        false => fallback.run(),
    }

The reason it is designed this way is that if you were to cache the rendered children, they could never be cleaned up but would leak forever; no on_cleanup would run, etc.

Your class:hidden approach is the correct way to keep something alive in the DOM but not shown.

I'm open to expanding the docs.rs docs for Show to clarify this.

gbj avatar Feb 12 '24 12:02 gbj

@gbj thanks for the explanation. i'd love a short note in https://docs.rs/leptos/latest/leptos/fn.Show.html about the rerendering. other than that we can close this.

should i do a PR?

qknight avatar Feb 12 '24 14:02 qknight

@qknight Sure, it'd be lovely to have a PR for that

benwis avatar Apr 09 '24 18:04 benwis