How to use object in van.state? #141
-
I haven't found a good way to use objects in a state, that's because accessing a property inside the state.val will cause the property to be rendered as a static value: const Counter = () => {
const countObj = van.state({count:0});
// won't update the nested count value in the UI
return button({onclick: () => countObj.val = {count: countObj.val.count + 1}}, countObj.val.count);
} This issue can make working declaratively with values like objects and arrays unreasonably complicated since the only way I know of to solve the issue is by declaring a new state for the nested count value: const Counter = () => {
const countObj = van.state({count:0});
const count = van.derive(() => countObj.val.count);
// will update the UI successfully
return button({onclick: () => countObj.val = {count: countObj.val.count + 1}}, count);
} Of course, this example is unrealistic, but when working on a real project this can cause the code to be bloated and hard to understand and maintain. A possible solution would be to automatically convert object values to states, this is a bit counterintuitive, but here is some code that does that: // utilities
type ConvertToState<T> = {
[K in keyof T]: T[K] extends object
? State<ConvertToState<T[K]>>
: State<T[K]>;
};
const isObject = (variable: any): boolean => {
return (
typeof variable === "object" &&
variable !== null &&
!(variable instanceof Array)
);
};
// main function
const nest = <T extends Record<string, any> = {}>(value: T) => {
const state: State<ConvertToState<T>> = van.state(value) as unknown as State<
ConvertToState<T>
>;
for (const [key, val] of Object.entries(state.val)) {
if (isObject(val) && !val?.val) {
(state.val[key] as any) = nest(val);
} else if (!isObject(val) && !val?.val) {
(state.val[key] as any) = van.state(val);
}
}
return state;
}; I hope there is a better solution. |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 4 replies
-
Hi @yahia-berashish, Thanks so much for your kind remarks!
For some of the things that you mentioned, VanJS already has decent support. For instance:
Oops, I found that you edited the original post while I was replying. This is my (partial) reply to your original post anyway. For your comments regarding adding more add-ons: yes, add-ons are definitely welcome! I am currently working on one: VanX. You can take a look at the WIP branch to have a sneak peek. I will take a look at the new version of the post and get back to you soon. |
Beta Was this translation helpful? Give feedback.
-
In VanJS, it's possible (and encouraged when appropriate) to define deeply nested state objects: In your example, it can be something like: const countObj = van.state({count: van.state(0)}) And yes, in VanX, we're going to provide a helper function that converts a deeply nested plain object into a deeply nested reactive state, so that you can use it more ergonomically. |
Beta Was this translation helpful? Give feedback.
Hi @yahia-berashish,
VanX was released just now: #144. Let me know if it provides the functionality that you're looking for.