How to update a table of textfields? (stop re-rendering when users type)

So, I essentially have a :
const [values, setValues] = createSignal<{a: string, b: string}[] | undefined>([]);

...

return <For each={values()}>{(entry, index) => (
<div>
<TextField
value={entry.a}
onChange={(e) => {
const new = [...values()!];
new[index()] = { ...new[index()], a: e.currentTarget.value };
setValues(new);
}}
/>
<TextField
value={entry.b}
onChange={(e) => {
const new = [...values()!];
new[index()] = { ...new[index()], b: e.currentTarget.value };
setValues(new);
}}
/>
</div>
)}</For>
const [values, setValues] = createSignal<{a: string, b: string}[] | undefined>([]);

...

return <For each={values()}>{(entry, index) => (
<div>
<TextField
value={entry.a}
onChange={(e) => {
const new = [...values()!];
new[index()] = { ...new[index()], a: e.currentTarget.value };
setValues(new);
}}
/>
<TextField
value={entry.b}
onChange={(e) => {
const new = [...values()!];
new[index()] = { ...new[index()], b: e.currentTarget.value };
setValues(new);
}}
/>
</div>
)}</For>
Unfortunately this means every time the user types a letter, the textfield looses focus, as the whole for-array is rerendered.
6 Replies
Brendonovich
Brendonovich5mo ago
you're recreating the whole array + object, instead just use fine grained updates
setLocalKeys(index(), 'a', e.currentTarget.value)
setLocalKeys(index(), 'a', e.currentTarget.value)
Bersaelor
Bersaelor5mo ago
ah, wow, I didn't know createSignal allowed such fine grained editing in case of arrays it always says Expected 0-1 arguments, but got 3.
Brendonovich
Brendonovich5mo ago
oh whoops you're using a signal switch to using a store
Bersaelor
Bersaelor5mo ago
so store behaves much more like the React state , I see
Brendonovich
Brendonovich5mo ago
hmm not really, signals are closer to react state stores are closer to mobx/valtio
Dakotys
Dakotys5mo ago
The problem was using For loop instead of Index loop, since For loop only moves elements and then changes the index signal or recreates the whole element at certain index (your case) during an update, whereas Index treats every value as a signal and when the signal updates it re sets the element's value just by using target.value which wont let the field loose focus. Its also mentioned on official website. https://www.solidjs.com/tutorial/flow_index#:~:text=if%20we%20used%20%3Cfor%3E%20to%20map%20a%20list%20of%20strings%20to%20%3Cinput%3E%20fields%20that%20could%20edit%20each%2C%20every%20change%20to%20that%20value%20would%20cause%20the%20%3Cinput%3E%20to%20be%20recreated. If you struggle with understanding the difference between For and Index loop check out List loop, it compbines the best from both worlds. https://github.com/solidjs-community/solid-primitives/tree/main/packages/list
Want results from more Discord servers?
Add your server