diff --git a/.changeset/clean-bulldogs-pump.md b/.changeset/clean-bulldogs-pump.md new file mode 100644 index 000000000..d0abf915e --- /dev/null +++ b/.changeset/clean-bulldogs-pump.md @@ -0,0 +1,5 @@ +--- +"@solid-primitives/list": patch +--- + +Fix for `` "unused" signal returning wrong values when read only after changes. (#791) diff --git a/packages/list/README.md b/packages/list/README.md index 3030abe4d..25c0b8d39 100644 --- a/packages/list/README.md +++ b/packages/list/README.md @@ -36,8 +36,7 @@ function Component() { {(value, index) => { return (
- {" "} - {index()}: {value()}{" "} + {index()}: {value()}
); }} @@ -54,7 +53,7 @@ Every element is keyed by item reference and index, but item reference is priori Underlying helper for `` unkeyed control flow. Returns array with elements mapped using provided mapping function. -Mapping function may use provided reactive value and reactive index, but signals for each of them are created only if they are used. Mapping function is ran only when original array has more elements than before. Elements are disposed only if original array has less elements than before. +Mapping function may use provided reactive value and reactive index. Mapping function is ran only when original array has more elements than before. Elements are disposed only if original array has less elements than before. ## Demo diff --git a/packages/list/src/index.ts b/packages/list/src/index.ts index 4996783e3..6893e2212 100644 --- a/packages/list/src/index.ts +++ b/packages/list/src/index.ts @@ -169,24 +169,22 @@ export function listArray( } function mapper(disposer: () => void) { const t: ListItem = { - value: newValue, - index: i, - disposer, - }, - scopedV = newValue, - scopedI = i; + value: newValue, + index: i, + disposer, + }; items.push(t); // signal created when used let sV: Accessor = () => { [sV, t.valueSetter] = isDev - ? createSignal(scopedV, { name: "value" }) - : createSignal(scopedV); + ? createSignal(t.value, { name: "value" }) + : createSignal(t.value); return sV(); }, sI: Accessor = () => { [sI, t.indexSetter] = isDev - ? createSignal(scopedI, { name: "index" }) - : createSignal(scopedI); + ? createSignal(t.index, { name: "index" }) + : createSignal(t.index); return sI(); }; diff --git a/packages/list/test/index.test.tsx b/packages/list/test/index.test.tsx index 74b55311a..2496a0f3c 100644 --- a/packages/list/test/index.test.tsx +++ b/packages/list/test/index.test.tsx @@ -302,4 +302,45 @@ describe("List", () => { unmount(); document.body.removeChild(container); }); + + test("later used signal reports correct values", () => { + const container = document.createElement("div"); + document.body.appendChild(container); + + const startingArray = [1, 2, 3]; + const [s, set] = createSignal(startingArray); + const callbacks: (() => { v: number; i: number })[] = []; + const unmount = render( + () => ( + + {(v, i) => { + // this could be event callback (eg. onClick), v & i read only later + function futureAction() { + return { + v: v(), + i: i(), + }; + } + callbacks.push(() => futureAction()); + + return
No signals used in this fn
; + }} +
+ ), + container, + ); + + set([2, 1, 4]); // swap 1,2 & replace 3 with 4 (swap for index update, replace for value update) + + // get entries, sort by index & check values in order + const values = callbacks + .map(x => x()) + .sort((a, b) => a.i - b.i) + .map(x => x.v); + + expect(values).toStrictEqual([2, 1, 4]); + + unmount(); + document.body.removeChild(container); + }); });