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

Nested for-loops in RSX render incorrectly #3021

Open
matthunz opened this issue Oct 1, 2024 · 1 comment
Open

Nested for-loops in RSX render incorrectly #3021

matthunz opened this issue Oct 1, 2024 · 1 comment
Labels
bug Something isn't working core relating to the core implementation of the virtualdom

Comments

@matthunz
Copy link
Contributor

matthunz commented Oct 1, 2024

Problem

Nested for-loops in RSX seem to render in an incorrect order 🤔 This was initially found by @DogeDark on dioxus-web, and I was able to reproduce and simplify the example on dioxus-desktop. Freya however doesn't seem to be affected, so this seems like a post-v0.6 bug.

Looking at the implementation, the for-loop is converted to an iterator of VNodes. My hunch is having the outer iterator call the inner one is leading to the ordering bug but the logic looks correct to me.

https://github.com/DioxusLabs/dioxus/blob/c2b131f249cc757716ca2c4d917cc9b8db98aa08/packages/rsx/src/forloop.rs#L52C31-L52C32

Steps To Reproduce

#[component]
fn App() -> Element {
    let mut data = use_signal(|| vec![vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]]);
    let mut next_value = use_signal(|| 10);

    let mut load_more = move || {
        let mut new_row = Vec::new();
        for _ in 0..10 {
            new_row.push(next_value());
            next_value += 1;
        }
        data.push(new_row);
    };

    rsx! {
        button {
            onclick: move |_| load_more(),
            "load more",
        }
        div {
            style: "display: grid; grid-template-columns: repeat(10, auto);",
 
            for row in data() {
                for column in row {
                    div{ key: "{column}", "{column}" }
                }
            }
        }
    }
}

Expected behavior
Separating the above nested loops with a temporary variable results in the following correct output:
Screenshot_2024-09-12_at_10 36 24_PM

Screenshots
However with the nested loop:
Screenshot_2024-09-12_at_10 35 09_PM

Environment:

  • Dioxus version: Latest git
  • Rust version: Nightly
  • App platform: Web + Desktop tested so far (so I think the issue resides in RSX itself)

Questionnaire

  • I'm interested in fixing this myself but don't know where to start
@ealmloff
Copy link
Member

ealmloff commented Oct 2, 2024

If you add many lists to the first render, they render correctly:

use dioxus::prelude::*;

#[component]
fn App() -> Element {
    let mut data = use_signal(|| {
        (0..100)
            .step_by(10)
            .map(|i| (i..i + 10).collect::<Vec<_>>())
            .collect::<Vec<_>>()
    });

    let mut load_more = move || {
        let mut new_row = Vec::new();
        let last = {
            let binding = data.last().unwrap();
            *binding.last().unwrap()
        };
        for i in 1..11 {
            new_row.push(last + i);
        }
        data.push(new_row);
    };

    rsx! {
        button {
            onclick: move |_| load_more(),
            "load more",
        }
        div {
            style: "display: grid; grid-template-columns: repeat(10, auto);",

            for (i, row) in data.iter().enumerate() {
                for column in row.iter() {
                    div{ "{column}" }
                }
            }
        }
    }
}

fn main() {
    launch(App)
}

Diouxs SSR doesn't use core diffing and it also renders the lists correctly. I think this is a bug with keyed list diffing (here). If it was a bug with rsx, then the initial list would render incorrectly as well

@ealmloff ealmloff added core relating to the core implementation of the virtualdom and removed rsx Related to rsx or the dioxus-rsx crate labels Oct 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working core relating to the core implementation of the virtualdom
Projects
None yet
Development

No branches or pull requests

2 participants