S
SolidJS16mo ago
wonrax

Difference between `setState` and `produce`?

I have appState as a store, and I'm trying to pass appState.selectedTable as a prop to a child component. When I simply use setAppState, it doesn't trigger a prop change in the child component. I've found that I need to use produce for it to work. The problem is, the documentation only gives a one-liner about the produce API. Could someone provide more information on how to properly use produce and createStore in this context?
No description
6 Replies
bigmistqke
bigmistqke16mo ago
produce is a pattern that comes from immer. The appState you receive as an argument is not the actual state, but a proxy. With immer each mutation is caught with the proxy and translated into an immutable data change, with solid it's similar, but then with a signal-store instead of immutable data. That being said, the first li should work too afaict.
wonrax
wonraxOP16mo ago
It doesn't in my case though and I still don't know why. The usage:
<TableView
class="overflow-auto"
table={appState.selectedTable}
connection={appState.connection!}
/>
<TableView
class="overflow-auto"
table={appState.selectedTable}
connection={appState.connection!}
/>
const TableView: Component<{
table?: DatabaseTable;
connection: DatabaseConnection;
class?: string;
}> = (props) => {
createEffect(() => {
console.log("createEffect table changed", props.table);
});
...
}
const TableView: Component<{
table?: DatabaseTable;
connection: DatabaseConnection;
class?: string;
}> = (props) => {
createEffect(() => {
console.log("createEffect table changed", props.table);
});
...
}
bigmistqke
bigmistqke16mo ago
If u could make reproducible example in solid's playground I can have a look at it
wonrax
wonraxOP16mo ago
I've been trying for a while and it seems impossible to make a reproducible code but this is the closest I can get: https://playground.solidjs.com/anonymous/ef126951-8ad2-4aa6-ac89-91bd1b40fb0b With this code the createEffect in the child component is registered and fired correctly (mine is not). But if you cycle through the buttons they behave weirdly. The first button you click will have its state changed when you click other buttons, my app also behaves like this. Maybe this is closely related to the problem.
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
bigmistqke
bigmistqke16mo ago
jaja. these references to keys of a store within a store. I remember I had difficulties with it at some point too. My solution back then was to do setStore({selectedTable: table}). I agree the default behaviour is indeed a bit unexpected. once you do setStore("selectedTable", table) this setStore("selectedTable", ...) becomes equivalent to setStore("tables", index-of-table, ...) I think it's the same principle why for example
const [store, setStore] = createStore({ subStore: { ... }});
const [subStore, setSubStore] = createStore(store.subStore);
setSubStore(...);
const [store, setStore] = createStore({ subStore: { ... }});
const [subStore, setSubStore] = createStore(store.subStore);
setSubStore(...);
this also works
Otonashi
Otonashi16mo ago
it's because of the merging behaviour of the store setter initially when it's undefined it sets selectedTable to table, but afterwards it's an object so it mutates the existing object (which is also stored elsewhere as table.something, which also gets mutated), instead of replacing the existing object as you might expect or if it helps setStore basically does this (in this specific case):
if (store.selectedTable && typeof store.selectedTable === "object") {
for (const key in table) {
store.selectedTable[key] = table[key];
}
} else {
store.selectedTable = table;
}
if (store.selectedTable && typeof store.selectedTable === "object") {
for (const key in table) {
store.selectedTable[key] = table[key];
}
} else {
store.selectedTable = table;
}
Want results from more Discord servers?
Add your server