How to modify array partially?

I'm using a store to store an array. I'm displaying that array in a For component. What I don't understand is how can I possibly use the "smart" feature of the For component, which only renders the changing part of the array. I mean all I can do in a store is setState(), where I put my full array in. So how can I possible send a partial update to a component? I see no way to push() at the end of an existing array in state or for example modify the last element of the array. What am I missing?
7 Replies
hyperknot
hyperknotOP16h ago
Is it possible that it's as simple as using reconcile? Does it do all the magical deduplication?
setStreamingMarkdown(text: string) {
const newTokens = getMarkdownTokens(text)
this.setState('streamingMarkdownTokens', reconcile(newTokens))
}
setStreamingMarkdown(text: string) {
const newTokens = getMarkdownTokens(text)
this.setState('streamingMarkdownTokens', reconcile(newTokens))
}
But how does it work? I mean how can reconcile compare two arrays if the only parameter it has is a single array?
REEEEE
REEEEE16h ago
reconcile would be the way to go. reconcile returns a function that takes in the previous state object. The store setter accepts a function as an argument where it provides you the previous value
setStore('streamingMarkdownToken', prevState => [...prevState, newItem])
setStore('streamingMarkdownToken', prevState => [...prevState, newItem])
Obviously creating a new array isn't ideal. You use reconcile here and it's equivalent to this
setStore('streamingMarkdownToken', prevState => reconcile(newTokens)(prevState))
setStore('streamingMarkdownToken', prevState => reconcile(newTokens)(prevState))
You can also use produce if you want to do mutation
setStore('streamingMarkdownTokens', produce(prevState => prevState.push(newItem)))
setStore('streamingMarkdownTokens', produce(prevState => prevState.push(newItem)))
hyperknot
hyperknotOP16h ago
I'm really happy with reconcile, basically it contains the same prefix matching algorithm which I was about to implement. It's super nice. One thing which isn't clear is it can take a key param. Is that totally optional? If my array consists of objects, does it do deep comparison if a key is not supplied?
REEEEE
REEEEE16h ago
I believe the key param is to uniquely identify objects by a property, the default key being id. Though I'm not 100% on that
peerreynders
peerreynders16h ago
If my array consists of objects, does it do deep comparison if a key is not supplied?
No. For arrays where the elements don't have a property to match the specified key (which defaults to "id" when not specified) elements are just correlated by array index. https://github.com/solidjs/solid/blob/29ab5bb1073b0f819b4bcd2022a66e1b9537f134/packages/solid/store/src/modifiers.ts#L102-L104 So in most cases simply inserting a new element in the middle of the array will defeat reconcile past that point, undermining its effectiveness.
GitHub
solid/packages/solid/store/src/modifiers.ts at 29ab5bb1073b0f819b4b...
A declarative, efficient, and flexible JavaScript library for building user interfaces. - solidjs/solid
hyperknot
hyperknotOP16h ago
I'm also reading the source code. What's interesting is that in my use case (streaming text, only the last section changes) it seems to work perfectly without supplying an id. And afaik the deep comparison happens because of the recursive nature of applyState
peerreynders
peerreynders15h ago
Well, if that's the case then it will probably work; however as the token list gets longer the deep comparison reconcile effort increases as well (especially if you (frequently) reconcile the entire list each time another token is appended; though it will probably take a while until it reaches React vDOM proportions).

Did you find this page helpful?