How to handle Reactivity for nested objects?

I have a tree structure which i want to render and have reactive to changes. The tree is in its own file and should not be mixed into solidjs or jsx stuff. When calling updateTree(node, id) the tree will update from that node (including) and outward the branch, meaning all nodes after that node needs to be updated/rerenderd. Below is some simplified example code. Thank you
interface treeNode {
id:number,
left:treeNode | null,
right:treeNode | null
}

const root:treeNode = {
id: 1,
left: {
id: 2,
left: null,
right: {
id: 4,
left: null,
right: null
}
},
right: {
id: 3,
left: null,
right: null
}
};

const [state, setstate] = createStore(root);

function update (node: treeNode): void {
// What should I put in here?
// Should I use produce?
const path: ('left'|'right')[] = getPath(node); // finds all root.left.right.left or whatever from root to the specific node
setstate(...path, node); // from example: setState("path", "to", "value", newValue); but i get error: A spread argument must either have a tuple type or be passed to a rest parameter.
};

const TreeTile:Component<{node:treeNode, update:(node: treeNode) => void}> = (props) => (
<Show when={props.node.left && props.node.right} fallback={
<button onClick={() => {
updateTree(new TreeNode(props.node, getNewId())); // This will change everything on this node and branch of the tree
props.update(props.node); // so here I'm updating the store/state to rerender everything from this branch.
}}>props.node.id</button>
}>
<TreeTile node={props.node.left!} update={props.update}/>
{props.node.id}
<TreeTile node={props.node.right!} update={props.update}/>
</Show>
);

render(() => <TreeTile node={state} update={update}/>, document.body);
interface treeNode {
id:number,
left:treeNode | null,
right:treeNode | null
}

const root:treeNode = {
id: 1,
left: {
id: 2,
left: null,
right: {
id: 4,
left: null,
right: null
}
},
right: {
id: 3,
left: null,
right: null
}
};

const [state, setstate] = createStore(root);

function update (node: treeNode): void {
// What should I put in here?
// Should I use produce?
const path: ('left'|'right')[] = getPath(node); // finds all root.left.right.left or whatever from root to the specific node
setstate(...path, node); // from example: setState("path", "to", "value", newValue); but i get error: A spread argument must either have a tuple type or be passed to a rest parameter.
};

const TreeTile:Component<{node:treeNode, update:(node: treeNode) => void}> = (props) => (
<Show when={props.node.left && props.node.right} fallback={
<button onClick={() => {
updateTree(new TreeNode(props.node, getNewId())); // This will change everything on this node and branch of the tree
props.update(props.node); // so here I'm updating the store/state to rerender everything from this branch.
}}>props.node.id</button>
}>
<TreeTile node={props.node.left!} update={props.update}/>
{props.node.id}
<TreeTile node={props.node.right!} update={props.update}/>
</Show>
);

render(() => <TreeTile node={state} update={update}/>, document.body);
9 Replies
REEEEE
REEEEE11mo ago
since it's recursive, I would use produce for this
TorHammare
TorHammare11mo ago
I still have not figured this out, since if i change something deeper than one step in the produce function, it is not recognized and wont update. Please let me know if you know any example or some code I can look at.
REEEEE
REEEEE11mo ago
If you can create a playground with what you have, I can take a look
TorHammare
TorHammare11mo ago
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
REEEEE
REEEEE11mo ago
I see. The main thing is that classes in Solid aren't reactive. There is a hack for it but it's not completely recommended as it may not work in the future You could move to using just js objects and the store to do appending and updates
TorHammare
TorHammare11mo ago
Yes, perhaps. The thing was though that I wanted a generic tree, which could also be any type of tree like different kinds of binary trees or even multi-trees. And use solid to represent it in different ways
REEEEE
REEEEE11mo ago
Here's the hack way to do it, I think createMutable might be in solid-primitives already or in the future https://playground.solidjs.com/anonymous/2c6c64a9-f10f-400e-b079-0e664b1d927b
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
TorHammare
TorHammare11mo ago
well that was an easy fix Could I change so that only the value field of the nodes is reactive? I guess that wouldn't work, it would not update the html structure. But cant I then add an useEffect which updates the html, dependent on when the value field changes?
REEEEE
REEEEE11mo ago
Depends on what you want to do I guess. You don't really need a createEffect, you should just be able to use the values in jsx unless you want to manually update the DOM