Blog>
Snippets

Virtual DOM - Diffing Algorithm

Exemplify the diffing process between the old and new Virtual DOM to understand how minimal updates are calculated.
// Simple vnode structure
function vnode(type, key, props, children) {
  return { type, key, props, children };
}

// Example of a diffing function
function diff(oldVNode, newVNode) {
  // If the oldVNode doesn't exist, we need to create the newVNode
  if (!oldVNode) {
    // Code to create new node goes here
  } else if (typeof newVNode === 'string' || typeof newVNode === 'number') {
    // If the newVNode is a string or a number (text node) and different from the old node,
    // we'll replace the old node's content
    if (newVNode !== oldVNode) {
      // Code to replace text node goes here
    }
  } else if (oldVNode.type !== newVNode.type) {
    // Nodes have different types, replace the old with the new node
    // Code to replace node goes here
  } else {
    // If the types are the same, we'll update the attributes/props
    updateProps(oldVNode.dom, oldVNode.props, newVNode.props);

    // Then, diff and patch the children
    diffChildren(oldVNode.children, newVNode.children);
  }
}
This code snippet represents a very simplified version of a diffing function in a Virtual DOM implementation. It checks whether there's no existing oldVNode (in which case it creates the newVNode), compares text nodes (strings or numbers), handles nodes with different types by replacing the old with the new, and updates nodes with the same type by updating their properties and recursively diffing their children.
// Update props
function updateProps(domElement, oldProps, newProps) {
  for (let key in oldProps) if (!(key in newProps)) domElement.removeAttribute(key);
  for (let key in newProps) {
    if (newProps[key] !== oldProps[key]) domElement.setAttribute(key, newProps[key]);
  }
}
This function takes a DOM element and two sets of properties (old and new) then updates the element's attributes by removing those not in the new props and setting those that have changed or been added.
// Diff children nodes
function diffChildren(oldChildren, newChildren) {
  let max = Math.max(oldChildren.length, newChildren.length);
  for (let i = 0; i < max; i++) {
    diff(oldChildren[i], newChildren[i]);
  }
}
The 'diffChildren' function iterates over children of the old and new VNodes, and calls the diff function for each pair of children. This ensures that the DOM updates are minimal by only updating what has changed.