Hello developers 🙂
I need help in understanding a piece of code that I developed recently.
My goal is to display a full binary tree (0 or 2 children allowed) which gives the user the ability to interact only with the leaves. The user can either split or remove a specific leaf.
- Upon split: set the splitted node as the left child of a new parent node.
- Upon remove: find the node's parent and replace it with node's sibling subtree.
Implementation details:
Node class
Represents the structure of the tree and supports:
- split()
- remove()
let id = 0
class Node {
constructor(parent, children){
this.id = id++
this.children = children? children : null
this.parent = parent? parent : null
}
split(){
const node = new Node(this.parent)
node.children = [this, new Node(node)]
this.parent = node
if (node.parent) {
// Replace parent's child (this) with node
}
return node
}
remove(){
const parent = this.parent
if (!parent) {
return this
}
const sibling = parent.children.find((child) => child !== this)
sibling.parent = parent.parent
if (parent.parent) {
// Replace grandparent's child (this.parent) with sibling
}
return sibling
}
}
TreeNode
Recursive component which contains node as a state
and renders the node's subtree.
function TreeNode(props) {
const [node, setNode] = useState(props.node)
useEffect(() => {
setNode(props.node)
return () => {
};
}, [props.node]);
const onRemove = () => {
const newNode = node.remove()
props.onRemove(newNode)
}
const onSplit = () => {
setNode(node.split())
}
return (
<div>
{
node.children?
<div>
<label>{node.id}</label>
<div>
<TreeNode node={node.children[0]} onRemove={setNode}/>
<TreeNode node={node.children[1]} onRemove={setNode}/>
</div>
</div>:
<div>
<button onClick={onRemove}>remove</button>
<button onClick={onSplit}>split</button>
<label>{node.id}</label>
</div>
}
</div>
)
}
The problem
Consider the tree I showed above (example - remove(3)), the actual result is:
Although the tree structure is correct.
So here is my question - why React doesn't change the DOM as I expected (as I showed in the above)?
I also noticed that React does change the DOM as I expected for this case:
Here is a full example in Sandbox: https://codesandbox.io/embed/full-binary-tree-react-21r77
Thanks in advance 🙏
Top comments (1)
Your onRemove never updates the state right? Also useEffect normally should be using an existing state and not setting state.