Skip to main content
All CollectionsFor WebTag Configuration
Single Page Apps – Working with React
Single Page Apps – Working with React
James Harber avatar
Written by James Harber
Updated over 11 months ago

How Single Page Apps work

AngularJS, VueJS and ReactJS, and frameworks like Next and Gatsby which use React as their underlying technology, all transform web pages in a similar pattern despite the implementation being vastly different.

  1. Old route container is unmounted/removed

  2. URL changes

  3. New route container is mounted/added

With this in mind, we can establish the correct way of hooking into page transitions using techniques described below.

Finding your route container

The easiest way of doing this is to inspect an element on the body of the page. Headings, images, etc. Avoid selecting app headers, which don't always follow the above pattern.

Then, move to another page by clicking through a link. You'll see most of the elements disappear, and what's left will most likely be your app container.

This is not an exact science, and so you may need some support from the our team or your own.

Setting up Mutation Observers

Mutation observers are hooks which trigger in the precise moment that an element changes. We use these to detect step #3 above, and are able to use it to act on the resulting new page before it becomes visible to users.

Note: the below code is an illustration - it uses ES6 and other code which is not supported in every browser, as well as open console logs. You should consider this and make sure your final code works in all browsers and that you're happy to publish it to all users.

// Triggers 
(function(){

const routecontainer = _ => {return document.querySelector('#root > .app > .contentContainer')};

let intvl = setInterval(_ => {

let el = routecontainer();
if(el){

clearInterval(intvl);

// --- Create and set a mutation observer

// Options for the observer (which mutations to observe)
const config = { childList: true, subtree: false };

// Callback function to execute when mutations are observed
let oldURL = location.pathname;
const callback = function(mutationsList, observer) {
if(location.pathname == oldURL) return; // nothing to see here.

// Has an update
console.log(`from ${oldURL} -- to ${location.pathname}`);
oldURL = location.pathname;

// dispatch an event
const event = new Event('wt-page-change');
document.dispatchEvent(event);

};

// Create an observer instance linked to the callback function
const observer = new MutationObserver(callback);

// Start observing the target node for configured mutations
observer.observe(el, config);

}

}, 500);

})();

Sometimes, you'll find similar pages where route containers don't unmount. In this situation, there's nothing stopping you from adding additional hooks/checks wherever makes sense. For example:

// ...
// Callback function to execute when mutations are observed
let oldURL = location.pathname;
const callback = function(mutationsList, observer) {
if(location.pathname == oldURL) return; // nothing to see here.

// Has an update
console.log(`from ${oldURL} -- to ${location.pathname}`);
oldURL = location.pathname;

// dispatch an event
const event = new Event('wt-page-change');
document.dispatchEvent(event);

// Add additional hook here.
document.getElementById('mybutton').addEventListener('click', ev => {
const event = new Event('wt-page-change');
document.dispatchEvent(event);
});

};
// ...

The wt-page-change event

This is the event that the above code triggers, and what we hook into when wanting to make transformations.

Acting on this event is handled in the SPA module that we insert into your tag, and as such you don't need to manually code anything further to lookup Locations or Projects/Tests.

Triggering the event from your codebase

If you find it easier or more reliable to do so, there is nothing stopping you from triggering the wt-page-change event from within your own codebase. You can use the same 2 lines as above to trigger it, and we'll then act whenever it's found. Please make sure you only trigger it once per page load though, to avoid duplicate rendering and tracking.

Server-side hydration

Hydration refers to the process of converting JavaScript into the HTML elements, using data Models etc.

It doesn't matter to us where this process of hydration happens, as we're not directly interfacing with the components that assemble our web page. We only care about the final rendered code, and being able to step in at the right moment to transform that code.

Did this answer your question?