diff --git a/examples/cypress/component/SimpleTodoList.cy.tsx b/examples/cypress/component/SimpleTodoList.cy.tsx
new file mode 100644
index 0000000..9417e17
--- /dev/null
+++ b/examples/cypress/component/SimpleTodoList.cy.tsx
@@ -0,0 +1,33 @@
+import React from "react"
+
+import { TodoList, store } from "../../react-todo/store/useTodos"
+import SimpleTodoListApp from "../../react-todo/SimpleApp"
+
+describe("SimpleTodoList", () => {
+ beforeEach(() => {
+ store.setState(new TodoList())
+ })
+
+ it("preserves list items references within store upon removal", () => {
+ cy.mount()
+
+ cy.findByTestId("add-todo-input").type("Clean the house")
+ cy.findByText("Add").click()
+
+ cy.findByTestId("add-todo-input").type("Walk the dogs")
+ cy.findByText("Add")
+ .click()
+ .then(() => {
+ const todo1 = store.state[0]
+ const todo2 = store.state[1]
+
+ cy.findByTestId(`todo-${todo1.id}`).within(() => {
+ cy.findByText("Delete").click()
+ })
+
+ cy.findByTestId(`todo-${todo2.id}`).within(() => {
+ cy.findByText("Delete").click()
+ })
+ })
+ })
+})
diff --git a/examples/cypress/component/TodoList.cy.tsx b/examples/cypress/component/TodoList.cy.tsx
index 5f71e37..c57ca69 100644
--- a/examples/cypress/component/TodoList.cy.tsx
+++ b/examples/cypress/component/TodoList.cy.tsx
@@ -79,4 +79,29 @@ describe("TodoList", () => {
cy.findByText("0 of 1 completed").should("exist")
})
})
+
+ it("preserves list items references within store upon removal", () => {
+ cy.mount()
+
+ cy.findByTestId("add-todo-input").type("Clean the house")
+ cy.findByText("Add").click()
+
+ cy.findByTestId("add-todo-input").type("Walk the dogs")
+ cy.findByText("Add").click()
+
+ cy.findByText("All")
+ .click()
+ .then(() => {
+ const todo1 = store.state[0]
+ const todo2 = store.state[1]
+
+ cy.findByTestId(`todo-${todo1.id}`).within(() => {
+ cy.findByText("Delete").click()
+ })
+
+ cy.findByTestId(`todo-${todo2.id}`).within(() => {
+ cy.findByText("Delete").click()
+ })
+ })
+ })
})
diff --git a/examples/react-todo/SimpleApp.tsx b/examples/react-todo/SimpleApp.tsx
new file mode 100644
index 0000000..5d4bdfd
--- /dev/null
+++ b/examples/react-todo/SimpleApp.tsx
@@ -0,0 +1,24 @@
+import React from "react"
+
+import Summary from "./components/Summary"
+import NewTodoForm from "./components/NewTodoForm"
+import SimpleTodoList from "./components/SimpleTodoList"
+
+import "./index.css"
+
+export default function SimpleApp() {
+ return (
+
+ )
+}
diff --git a/examples/react-todo/components/SimpleTodoList.tsx b/examples/react-todo/components/SimpleTodoList.tsx
new file mode 100644
index 0000000..e79de57
--- /dev/null
+++ b/examples/react-todo/components/SimpleTodoList.tsx
@@ -0,0 +1,17 @@
+import React, { memo } from "react"
+import { useArbor } from "@arborjs/react"
+
+import { TodoList, store } from "../store/useTodos"
+import TodoView from "./TodoView"
+
+export default memo(function SimpleTodoList() {
+ const todos = useArbor(store) as TodoList
+
+ return (
+
+ {todos.map((todo) => (
+
+ ))}
+
+ )
+})
diff --git a/examples/react-todo/components/TodoView.tsx b/examples/react-todo/components/TodoView.tsx
index 53be51a..9303351 100644
--- a/examples/react-todo/components/TodoView.tsx
+++ b/examples/react-todo/components/TodoView.tsx
@@ -10,7 +10,7 @@ export interface TodoProps {
export default memo(function TodoView({ id }: TodoProps) {
const [editing, setEditing] = useState(false)
- const todo = useArbor(store.state.find(t => t.uuid === id)!)
+ const todo = useArbor(store.state.find((t) => t.uuid === id)!)
return (
{
describe("Symbol.iterator", () => {
@@ -389,4 +390,18 @@ describe("Array", () => {
expect(subscriber).toHaveBeenCalledTimes(2)
})
})
+
+ it("preserves tree links when deleting items via detach", () => {
+ const state = [{ id: 1 }, { id: 2 }]
+
+ const store = new Arbor(state)
+ const scoped = new ScopedStore(store)
+ const item1 = scoped.state[0]
+ const item2 = scoped.state[1]
+
+ detach(item1)
+ detach(item2)
+
+ expect(store.state).toEqual([])
+ })
})