Skip to content

Commit a67c0e3

Browse files
authored
Fix for <List> "unused" signal (#791)
2 parents 0037773 + 2f06d07 commit a67c0e3

File tree

4 files changed

+56
-13
lines changed

4 files changed

+56
-13
lines changed

.changeset/clean-bulldogs-pump.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@solid-primitives/list": patch
3+
---
4+
5+
Fix for `<List>` "unused" signal returning wrong values when read only after changes. (#791)

packages/list/README.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,7 @@ function Component() {
3636
{(value, index) => {
3737
return (
3838
<div>
39-
{" "}
40-
{index()}: {value()}{" "}
39+
{index()}: {value()}
4140
</div>
4241
);
4342
}}
@@ -54,7 +53,7 @@ Every element is keyed by item reference and index, but item reference is priori
5453

5554
Underlying helper for `<List>` unkeyed control flow. Returns array with elements mapped using provided mapping function.
5655

57-
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.
56+
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.
5857

5958
## Demo
6059

packages/list/src/index.ts

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -169,24 +169,22 @@ export function listArray<T, U>(
169169
}
170170
function mapper(disposer: () => void) {
171171
const t: ListItem<T> = {
172-
value: newValue,
173-
index: i,
174-
disposer,
175-
},
176-
scopedV = newValue,
177-
scopedI = i;
172+
value: newValue,
173+
index: i,
174+
disposer,
175+
};
178176
items.push(t);
179177
// signal created when used
180178
let sV: Accessor<T> = () => {
181179
[sV, t.valueSetter] = isDev
182-
? createSignal(scopedV, { name: "value" })
183-
: createSignal(scopedV);
180+
? createSignal(t.value, { name: "value" })
181+
: createSignal(t.value);
184182
return sV();
185183
},
186184
sI: Accessor<number> = () => {
187185
[sI, t.indexSetter] = isDev
188-
? createSignal(scopedI, { name: "index" })
189-
: createSignal(scopedI);
186+
? createSignal(t.index, { name: "index" })
187+
: createSignal(t.index);
190188
return sI();
191189
};
192190

packages/list/test/index.test.tsx

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,4 +302,45 @@ describe("List", () => {
302302
unmount();
303303
document.body.removeChild(container);
304304
});
305+
306+
test("later used signal reports correct values", () => {
307+
const container = document.createElement("div");
308+
document.body.appendChild(container);
309+
310+
const startingArray = [1, 2, 3];
311+
const [s, set] = createSignal(startingArray);
312+
const callbacks: (() => { v: number; i: number })[] = [];
313+
const unmount = render(
314+
() => (
315+
<List each={s()}>
316+
{(v, i) => {
317+
// this could be event callback (eg. onClick), v & i read only later
318+
function futureAction() {
319+
return {
320+
v: v(),
321+
i: i(),
322+
};
323+
}
324+
callbacks.push(() => futureAction());
325+
326+
return <div>No signals used in this fn</div>;
327+
}}
328+
</List>
329+
),
330+
container,
331+
);
332+
333+
set([2, 1, 4]); // swap 1,2 & replace 3 with 4 (swap for index update, replace for value update)
334+
335+
// get entries, sort by index & check values in order
336+
const values = callbacks
337+
.map(x => x())
338+
.sort((a, b) => a.i - b.i)
339+
.map(x => x.v);
340+
341+
expect(values).toStrictEqual([2, 1, 4]);
342+
343+
unmount();
344+
document.body.removeChild(container);
345+
});
305346
});

0 commit comments

Comments
 (0)