Skip to content

Nested Reactive Store panics with Index out of bounds #4475

@godstail

Description

@godstail

Describe the bug
Nested Stores produce panics of "Index out of bounds"

Leptos Dependencies

leptos = { version = "0.8", features = ["csr"] }
leptos_meta = { version = "0.8" }
leptos_router = { version = "0.8" }
reactive_stores = "0.3"

To Reproduce
showcase snippet with instructions and buttons to click:

use leptos::prelude::*;
use reactive_stores::Store;

#[derive(Clone, Debug, Default, PartialEq, Eq, Store)]
pub struct MyStore {
    #[store(key: i32 = |row| row.id)]
    pub inners: Vec<MyInner>,
}

#[derive(Clone, Debug, Default, PartialEq, Eq, Store)]
pub struct MyInner {
    pub id: i32,
    #[store(key: i32 = |row| row.id)]
    pub subs: Vec<MySubInner>,
}

#[derive(Clone, Debug, Default, PartialEq, Eq, Store)]
pub struct MySubInner {
    pub id: i32,
    pub text: String,
}

#[component]
pub fn StoresTests() -> impl IntoView {
    let my_store = Store::new(MyStore {
        inners: vec![
            MyInner {
                id: 1,
                subs: vec![
                    MySubInner {
                        id: 101,
                        text: "sub_101".to_string(),
                    },
                    MySubInner {
                        id: 102,
                        text: "sub_102".to_string(),
                    },
                ],
            },
            MyInner {
                id: 2,
                subs: vec![
                    MySubInner {
                        id: 201,
                        text: "sub_201".to_string(),
                    },
                    MySubInner {
                        id: 202,
                        text: "sub_202".to_string(),
                    },
                ],
            },
        ],
    });

    view! {
        <h2>"Index out of bounds"</h2>
        <p>"1. edit any field"</p>
        <p>"2. change focus (click outside)"</p>
        <p>"3. click any delete sub from the same inner or any delete inner"</p>
        <p>"(for some reason deleting just edited sub without changing focus sometimes works)"</p>
        <br/>
        <For
            each=move || my_store.inners()
            key=|row| row.read().id
            children=move |inner| {
                let inner_id = inner.id().get();
                view! {
                    <For
                        each=move || inner.subs()
                        key=|row| row.read().id
                        children=move |sub| {
                            let sub_id = sub.id().get();
                            view! {
                                <span style="display: flex; gap: 8px;">
                                    {move || format!("id: {}, text: {}", sub.id().get(), sub.text().get())}
                                    <input bind:value=sub.text() />
                                    <button on:click=move |_| {
                                        request_animation_frame(move || {
                                            inner
                                                .update(|inn| {
                                                    inn.subs.retain(|s| s.id != sub_id)
                                                });
                                        });
                                    }>"delete sub"</button>
                                </span>
                                <br/>
                            }
                        }
                    />
                    <button on:click=move |_| {
                        request_animation_frame(move || {
                            my_store
                                .update(|ms| {
                                    ms.inners.retain(|inn| inn.id != inner_id)
                                });
                        });
                    }>"delete inner"</button>
                    <br/>
                    <br/>
                }
            }
        />
    }
}

Next Steps

  • I will make a PR
  • I would like to make a PR, but need help getting started
  • I want someone else to take the time to fix this
  • This is a low priority for me and is just shared for your information

Additional context
Index out of bounds panic doesn't appear with reactive_stores 2.5 in this simple example, only with 3.0.
But it does appear in 2.5 in more complicated cases.

If I first reduce Inner collection to 1 sub and then edit+delete the last remaining sub, panic doesn't appear.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions