How to make sure the function "window.location.reload()" only fires once instead of having an infinite loop?

Viewed 1177

I was trying to add an accessibility feature to my web page, which is built with React.js, to make sure that the color of my banner doesn't get affected by the high contrast plugin of Chrome.

I tried to implement it that by adding a function to detect whether the Chrome plugin has been turned on, and my code should toggle a class to make sure the banner color won't change much in the high contrast mode. I noticed that this change could only be seen after refreshing the page, so I added this line of code window.location.reload() to manually reload the page.

The problem is, this part of code enters into an infinite loop and my page just won't stop reloading. I tried to replace the reloading part with other methods, the results were still the same. Here's the code of my React Component:

 componentDidMount = () => {
    this.keepBannerColor()
}


keepBannerColor() {
    // these two lines of code below is tell whether the browser is chrome
    let userAgentString = navigator.userAgent;
    let chromeAgent = userAgentString.indexOf("Chrome") > -1;
    let header = document.querySelector('.mizaru-header')

    if (header && chromeAgent) {
        console.log('funciton triggered')
        let htmlTag = document.getElementsByTagName('html');
        let isInverted = htmlTag[0].getAttribute('hc') != null
        header.classList.toggle('inverted', isInverted)
        window.location.reload()
    }
}

Here's my CSS code for the toggle class: .inverted{ filter: invert(100%); }

Any help would be nice!

2 Answers

Why don't you try save an indicator into localstorage or sessionstorage, and add this validation in your if condition:

Snippet of your code:

...
// Use local or session storage
let hasReloaded = localStorage.getItem('hasReloaded')

if (header && chromeAgent && !hasReloaded) {
  console.log('funciton triggered')
  let htmlTag = document.getElementsByTagName('html');
  let isInverted = htmlTag[0].getAttribute('hc') != null
  header.classList.toggle('inverted', isInverted)
  // Set hasRealoaded to true
  localStorage.setItem('hasReloaded', true)
  window.location.reload()
}
...

You don't need a page reload for this, you need MutationObserver.

This will look for changes in the document on a particular element.

As the hc attribute is added to the page dynamically this will listen for when it is added or removed.

The below will log "High Contrast", "a4" if the high contrast mode is switched on (with the "a4" changing depending on the settings) and "High Contrast Off" if the plugin is not active.

The beauty of the below is that depending on the setting "a3", "a4" etc. you can apply different styling.

There is something not right with the below as if fires "High Contrast Off" twice when the plugin is disabled so you will need to investigate that. (This is because when the plugin is toggled off it first sets the state to "a0" and then removes the attribute, under normal use it should be fine but just something to be aware of).

  const targetNode = document.documentElement;

// Options for the observer (which mutations to observe)
const config = { attributes: true};

// Callback function to execute when mutations are observed
const callback = function(mutationsList, observer) {
    // Use traditional 'for loops' for IE 11
    
    let name = "";
    
    for(let mutation of mutationsList) {
       if (mutation.type === 'attributes') {
           if(mutation.attributeName == "hc"){
               if(mutation.target.attributes.getNamedItem(mutation.attributeName) != null && mutation.target.attributes.getNamedItem(mutation.attributeName).value != "a0"){
               console.log("High Contrast", mutation.target.attributes.getNamedItem(mutation.attributeName).value);
           }else{
               console.log("High Contrast Off");
           }
           }
            
        }
    }
};

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

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

Related