Reconcile array of nested objects

Hi. I'm having an issue where I do an api call and I get back facets and whenever you select a value for a facet you get another list of facets back. Now I'm using reconcile to update the store and it mostly works. However, when I get a new list with a new facet in front and after, in my case the Category facet, it rerenders the entire category facet. I've setup some test data here to check it out: https://playground.solidjs.com/anonymous/59500506-e221-4e9a-9d2b-70a3e8fc60d7 So even though I reconcile based on the "key" key, it still sees it as a different object because of it's placement in the array or something? Anyone know how to fix this or is it a bug of some sort?
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
4 Replies
Madaxen86
Madaxen864w ago
That's because you essentially overwriting the whole array. You can use the produce helper for the store to mutate the data in place and only add and remove data granularly. (https://playground.solidjs.com/anonymous/94443527-b5f8-4e1e-b35e-4b0b09de87d0)
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
Dastrus
DastrusOP4w ago
To be honest, I find it confusing in how that works. Since it works when the array gets changed in a smaller size in my example. So I would think that in that case the array would be overwritten as well. Or when I toggle using the last entry in the array. But it only seems to rerender the category one. Your solution does seem to work however (and I understand why), so I guess I'll try to implement my logic in that way. Thank you for your help. By the way, when sorting by sequence after adding the new data seems to break the Category facet, same as with reconcile. The .sort method should however alter the array instead of creating a new one (as with toSorted()). Using unshift and push does seem to work however. Does that mean there is some kind of bug with arrays in stores? Or does .sort() still create a new array in some way that I don't know of? // Does not work toggledData.forEach((item) => prev.facets.push(item)); prev.facets.sort((a, b) => a.sequence - b.sequence); // Works prev.facets.unshift(toggledData[0]); prev.facets.push(toggledData[1]);
// This causes rerenders
setStore(
produce((prev) => {
return prev.facets.sort((a, b) => !toggle() ? a.sequence - b.sequence : b.sequence - a.sequence);
}),
);
// This causes rerenders
setStore(
produce((prev) => {
return prev.facets.sort((a, b) => !toggle() ? a.sequence - b.sequence : b.sequence - a.sequence);
}),
);
Madaxen86
Madaxen864w ago
I don't see "re-renders": This works as I would expect:https://playground.solidjs.com/anonymous/0ecedb0c-2aa4-4834-bdd6-473de72d01a0
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
Dastrus
DastrusOP4w ago
when you tab to a checkbox and select it with spacebar for example it re-renders when the facets expand (so when Price and Bloemkleur get added). When the facets shrink the focus stays on the correct checkbox. I'm using chrome, so not sure if different browsers handle it differently. I see that the problem exists when a new item gets placed in front and after the existing item. I've played around with splice (prev.facets.splice(2, 0, toggledData.find(d => d.key === 'flower_color'));) and that resulted in the focus being lost. Same goes for unshift and push if I remove "Bijzondere boom" from the initial array. And regarding the re-render, I see that it doesn't print the console.log you've placed, but when I inspect the element through the element inspector it does seem to recreate the div. Ok, that's a bummer. Do you perhaps know if there's a way in Solid to make it work? Because I'm trying to implement rendering a list of facets (which are retrieved from an API and can change when selecting a certain value for a facet) and I'm trying to make it WCAG friendly, which means losing focus is not very user friendly for the people who rely on their keyboard to navigate the UI. Alright, was hoping to avoid that but guess there's no other way. Thanks! Thanks for the example 👍

Did you find this page helpful?