DEV Community

Rache4
Rache4

Posted on

Unexpected Behavior of React DOM Modification

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.

  1. Upon split: set the splitted node as the left child of a new parent node. Example - split(1)
  2. Upon remove: find the node's parent and replace it with node's sibling subtree. Example - remove(3)

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 } } 
Enter fullscreen mode Exit fullscreen mode

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>  ) } 
Enter fullscreen mode Exit fullscreen mode

The problem

Consider the tree I showed above (example - remove(3)), the actual result is:
Actual result - remove(3)

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:
Actual result - remove(1)

Here is a full example in Sandbox: https://codesandbox.io/embed/full-binary-tree-react-21r77

Thanks in advance πŸ™

Top comments (1)

Collapse
 
wclayferguson profile image
Clay Ferguson

Your onRemove never updates the state right? Also useEffect normally should be using an existing state and not setting state.