skrebbel
skrebbel
SSolidJS
Created by skrebbel on 2/16/2024 in #support
captureStoreUpdates vs reconcile
Hi! I'm trying to get a stream of immutable object values from a store. The store is frequently updated from a data source that sends big chunky records with minimal actual changes, so I use reconcile to keep the amount of signalled changes to a minimum. This works very well, but the captureStoreUpdates primitive from https://primitives.solidjs.community/package/deep somehow doesn't play ball and I can't figure out why not.
const [state, setState] = createStore({ foo: { dummy: "a", count: 1 } });
const increment = () =>
setState(
reconcile(
{ foo: { dummy: "a", count: state.foo.count + 1 } },
{ merge: true },
),
);

const getDelta = captureStoreUpdates(state as any);
createEffect(() => {
const delta = getDelta();

// after an increment(), i'd expect to get:
// [{path: ["foo", "count"], value: 2}]
// but i get the entire reconciled value:
// [{path: ["foo"], value: {dummy: "a", count: 2}}]
console.log("delta:", delta);
});
const [state, setState] = createStore({ foo: { dummy: "a", count: 1 } });
const increment = () =>
setState(
reconcile(
{ foo: { dummy: "a", count: state.foo.count + 1 } },
{ merge: true },
),
);

const getDelta = captureStoreUpdates(state as any);
createEffect(() => {
const delta = getDelta();

// after an increment(), i'd expect to get:
// [{path: ["foo", "count"], value: 2}]
// but i get the entire reconciled value:
// [{path: ["foo"], value: {dummy: "a", count: 2}}]
console.log("delta:", delta);
});
Full playground example: https://playground.solidjs.com/anonymous/f5d92603-c66c-4d00-82ba-9cce9ca452fe Is there any way to get captureStoreUpdates to only see the data that actually changed, post reconcile, and to not have it assume that the entire object changed?
7 replies
SSolidJS
Created by skrebbel on 2/10/2024 in #support
Derived data in a store vs reconcile
Hey there, I'm trying to somehow have derived/computed data sit in a rather deeply nested store, ie values that depend on "real" values stored in the store. The docs suggests getters, and that works fine, until I try to use reconcile:
const [state, setState] = createStore({
a: 5,
b: 6,
get c() { return state.a + state.b; }
});

setState(reconcile({ a: 7, b: 6 }));
console.log(state.c); //error, `c` got deleted
const [state, setState] = createStore({
a: 5,
b: 6,
get c() { return state.a + state.b; }
});

setState(reconcile({ a: 7, b: 6 }));
console.log(state.c); //error, `c` got deleted
Our data is a particularly great fit for reconcile, it'd be a shame to not be able to use that. In the end I found a workaround, which is to make a field data with the all the raw data in it (and reconcile that), and put the getters one level higher in the hierarchy. Is that the recommended approach? Or is there a different way to have reconcile leave the setters be? I noticed that with a class (returning createMutable(this) from the constructor) it actually works, ie I can put instances of that class in a store and reconcile on the fields, and the getters/methods aren't touched because they're on the prototype and not the instance. But I don't love it because, even though I really like classes/OO, I don't really love making them fully mutable for all the reasons Ryan likes to cite. I'd totally go for an immutable class, F# with style, but I've yet to find an elegant way to accomplish that with JS (let alone solid stores / reconcile). Any ideas? Thanks!
7 replies