Mutation observer in React

Posted by everrover on March 11, 2022

#js
#observers
#react
#reacthooks
#webdevelopment

Function in a nutshell (a long one)

Mutation observer observes the changes in the DOM in respect to three types of updates

  • Addition and removal of child elements
  • Element attributes
  • Text changes

These updates can be monitored on three levels.

  • On the element under observation
  • On the direct descendants
  • On all the descendants

Additionally it can track previous changes as well. Kind of like for undo. This can be done for text changes and attribute changes.

The config object

json
{
  childList: true, // 1
  attributes: true, // 2
  characterData: false, // 3, Atleast one of 1,2,3 should be true
  subtree: false, // can work with all
  attributeFilter: ['one', 'two'], // can work with 2
  attributeOldValue: false, // can work with 2
  characterDataOldValue: false // can work with 3
}

Of the top three configs, at least one of them should have a true value. Here's a short synopsis of each of these...

  • childList : Monitors only the monitored element and direct descendant elements of it
  • attributes : Monitors changes in attributes of elements in observation
  • characterData : Monitors only text changes in the monitored elements

These configs augment the monitoring functionality by increasing or decreasing the scope of observation

  • subtree : Used in conjunction with all. It allows us to monitor all the descendants for a given monitored element
  • characterDataOldValue: Used with third one. This will return the last text value of a monitored element in entry response.
  • attributeOldValue : Used with second one. This will return the last attribute value in use within attribute of a monitored element in entry response.
  • attributeFilter : Used with second one. This will restrict the attributes being monitored to the ones present within the list. If blank list is provided nothing is monitored. If this returns false value every attribute is monitored.

The mutation entry object

  • addedNodes and removedNodes includes elements and immediate child-elements added or removed from the DOM, under the element in observation. Monitored using childList: true. Will include all descendant changes if subtree: true
  • attributeName includes element attribute name of changed attribute within the DOM under the elements in observation. Monitored using attributes: true. Current attribute values will be within target props
  • oldValue includes element old attribute value or old character data value if attributeOldValue or characterDataOldValue is true .
  • Current values of element will be within target props
  • nextSibling and previousSibling : As the name suggests...
  • type includes the type of event. Value will be one amongst childList, attributes and characterData as per the mutation event.

Basic syntax

First off, same MutationObserver can monitor changes in multiple elements, each with a different configuration. Here's the constructor. It only takes in a callback function as input.

jsx
const observer = new MutationObserver((entries, observer)=>{
	// callback function
  entries.forEach((entry, idx) => /** do osomething with entry object **/)
})

Here's the observation call, unobserve call and disconnect

jsx
observer.observe(target, configs) # observe specific target element
observer.unobserve(target) # unobserve specified target element
observer.disconnect() # unobserve all target elements

Lastly we have an interceptor(this won’t allow the mutation trigger to reach the callback),

const records = observer.takeRecords()

I've built a demo. Do check it out. It'll explain more about it than these words I guess.

Here is a demo for this observer.

Practical use-cases

I can't be really sure about core JS applications. But in respect to React.js it is useful to monitor mutations in DOM made via third party packages. This can help us in taking certain required actions on making certain mutations and changes of our own. Example being Syntax Highlighting or loading hyperlink views, amongst many unknown to me. Help me with that on my post here.

References