Skip to content

Incorrect Component State Preservation When Removing Items from List #4971

@git-lloyd

Description

@git-lloyd

Problem

When removing an item from a list, the state of remaining components is not properly preserved, leading to incorrect rendering of component internal state. code example:

use dioxus::prelude::*;

fn main() {
    dioxus::launch(App);
}

#[component]
fn App() -> Element {
    let tab_items = use_signal(|| vec!["a".to_string(), "b".to_string(), "c".to_string()]);

    rsx! {
        Tabs {
            tab_items,
        }

        // details
        for tab_item in tab_items() {
            br {}
            div {
                key: "{tab_item}",
                Detail { path: tab_item.clone() }
            }
        }
    }
}

#[component]
fn Tabs(tab_items: Signal<Vec<String>>) -> Element {
    rsx! {
        for tab_item in tab_items() {
            TabItem {
                tab_item: tab_item,
                tab_items,
            }
        }
    }
}

#[derive(Props, PartialEq, Clone)]
struct TabItemProps {
    #[props(default)]
    pub tab_item: String,

    #[props(default)]
    pub tab_items: Signal<Vec<String>>,
}

#[component]
fn TabItem(props: TabItemProps) -> Element {
    let tab_item = props.tab_item.clone();
    rsx! {
        button {
            onclick: move |_| {
                let mut tab_items = props.tab_items;
                tab_items.retain(|t| !t.eq(&tab_item));
            },
            {props.tab_item}
        }
    }
}

#[component]
fn Detail(path: String) -> Element {
    let default = path.clone();
    let content = use_signal(|| default);
    rsx! {
        {path}
        {content()}
    }
}

Steps To Reproduce

  1. Create a list of items with associated components that have internal state
  2. Click to remove a middle item from the list
  3. Observe that the remaining components' internal state gets mixed up

Expected behavior

When clicking the "b" button, the page should display components for "a" and "c", with each component maintaining its correct internal state:

  • Component for "a" should display "aa"
  • Component for "c" should display "cc"

Actual Behavior

When clicking the "b" button, the components display incorrect state:

  • Component for "a" displays "aa" (correct)
  • Component for "c" displays "cb" (incorrect - should be "cc")

Screenshots

Image

Environment:

  • Dioxus version: 0.7.1
  • Rust version: 1.91.0
  • OS info: win11
  • App platform: web

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingcorerelating to the core implementation of the virtualdomrsxRelated to rsx or the dioxus-rsx crate

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions