65

Is there any way to detect IE browser with React and either redirect to a page or give any helpful message. I found something in JavaScript, but not sure how would I use it with React+TypeScript.

var isEdge = !isIE && !!window.StyleMedia;

10 Answers 10

95

You are on the right track you can use these to conditionally render jsx or help with routing...

I have used the following with great success.

Originally from - How to detect Safari, Chrome, IE, Firefox and Opera browser?

// Opera 8.0+
const isOpera = (!!window.opr && !!opr.addons) || !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;

// Firefox 1.0+
const isFirefox = typeof InstallTrigger !== 'undefined';

// Safari 3.0+ "[object HTMLElementConstructor]" 
const isSafari = /constructor/i.test(window.HTMLElement) || (function (p) { return p.toString() === "[object SafariRemoteNotification]"; })(!window['safari'] || (typeof safari !== 'undefined' && safari.pushNotification));

// Internet Explorer 6-11
const isIE = /*@cc_on!@*/false || !!document.documentMode;

// Edge 20+
const isEdge = !isIE && !!window.StyleMedia;

// Chrome 1 - 71
const isChrome = !!window.chrome && (!!window.chrome.webstore || !!window.chrome.runtime);

// Blink engine detection
const isBlink = (isChrome || isOpera) && !!window.CSS;

Please be aware they each stand a chance to deprecated due to browser changes.

I use them in React like this:

 content(props){
    if(!isChrome){
     return (
      <Otherjsxelements/>
     )
    }
    else { 
     return (
      <Chromejsxelements/>
     )
    }
  }

Then by calling {this.Content()} in my main component to render the different browser specific elements.

Pseudo code might look something like this... (untested):

import React from 'react';

const isChrome = !!window.chrome && (!!window.chrome.webstore || !!window.chrome.runtime);

export default class Test extends React.Component {

  content(){
    if(isChrome){
        return (
            <div>Chrome</div>
        )
    } else {
        return (
            <div>Not Chrome</div>
        )
    }
  }

    render() {
        return (
            <div>Content to be seen on all browsers</div>
            {this.content()}
        )
    }
}
Sign up to request clarification or add additional context in comments.

5 Comments

You could have this change modal content for instance, or even depending on your router have it call a function and redirect you to a help page. Please just let me know if you need an additional breakdown of where these parts each fit inside of the component.
It might be a good idea to look into a library like the one @Tallboy provided as that stands a better chance of being updated more regularly. Then just use the example I provided for the React integration.
Maybe try this... let isSafari = navigator.userAgent.indexOf("Safari") > -1; these methods are changed fairly often.
These are now deprecated
As mentioned, isChrome only works upto version 71. But can't use it for current version 95. This is not a solution for chrome then.
37

Not sure why but nobody mentioned this package: react-device-detect The package have a lot browsers checks, plus versions and some other info related. It's really small and it's updated.

You can use:

import { isIE } from 'react-device-detect';
isIE // returns true or false

react-device-detect it's also very small bundlephobia link

5 Comments

Sure, I got it now @HafizTemuri , but maybe you should try to add that info on your next question, we're devs, not clairvoyants. In my personal opinion the package save us a good time in some ways: firstly because you don't have to make any code yourself and secondly you'll not spend time refactoring that code because some browser version doesn't support your code any more. I enforce the info about the package size because, in my personal opinion, in this case a light package is not an overkill, an overkill is spend time with premature optimization. wiki.c2.com/?PrematureOptimization
I don't think it's useful to put down this post. A package is a perfectly reasonable way to approach the issue, and does have several advantages, namely that the creator/contributors may have thought of edge cases that you haven't, and that what works and doesn't with device/browser detection changes frequently; I personally would rather not have to update my code every time it does.
Although I'm a bit late to the discussion, @LucasAndrade was only trying to be helpful. No matter how good one may be in programming, there will almost always be edge cases to miss.
@LucasAndrade Seems like someone deleted my comment, but it was in my question in case you missed it, not sure how would I use it with React+TypeScript. Packages are good until they get bugs and you overturn everything to update a package, only to realize its filled with bugs, then you spend extra time to downgrade. My theory is, write it yourself if you can. And for such a small problem, I don't think anyone should be using a package. And of course there needs to be a balance there, don't go in other direction and try to re-invent the wheel.
I just used this package, accessed on Safari and it doesn't work
8

This is the service I always use when doing JS/Browser based browser-detection: http://is.js.org/

if (is.ie() || is.edge()) {
  window.location.href = 'http://example.com';
}

5 Comments

This could end up in never ending redirect loop. This is not an ideal way of handling it in my opinion.
How would an infinite redirect happen in my case? You simply would ensure that doesn't happen on that page. How else would you redirect to a page based on browser though without creating a situation for a potential redirect loop?
You said in your original message, "redirect to a page", so I answered exactly what you asked.
Not to mention, the answer you just marked as correct is identical to my answer without the redirect, which was what you originally asked for.
redirect to a page of the same application. It could end up in the same if statement and making it redirect over and over again.
2

I was using Gatsby for our React site and build was giving me trouble with the accepted answer, so I ended up using a useEffect on load to be able to not render for IE at a minimum:

  const [isIE, setIsIE] = React.useState(false);

  React.useEffect(() => {
    console.log(`UA: ${window.navigator.userAgent}`);
    var msie = window.navigator.userAgent.indexOf("MSIE ");
    setIsIE(msie > 0)
  }, []);

  if(isIE) {
    return <></>
  }

// In my component render

if(isIE) { return <></> }

Got the idea originally from:

https://medium.com/react-review/how-to-create-a-custom-usedevicedetect-react-hook-f5a1bfe64599

and

Check if user is using IE

3 Comments

What kind of troubles? I personally don't like the use of state and useEffect here. You can still implement this approach with a static const outside the component. const isIE = window.navigator.userAgent.indexOf("MSIE ") > 0. You can still keep the check in your component. if (isIE)
@HafizTemuri use of document or documentMode in gatsby build throws a variety of errors and it also has trouble using window logic on build as well. By putting inside a hook, it doesn't run on build and allows HTML to be compiled fully, and then on run, actually define the variables.
and people use a framework like that? That would drive me nuts if I cannot use window object. And a lot of time we don't need to put things in useState. They should have a window available especially when they claim to generate static HTML.
1

Try:

const isEdge = window.navigator.userAgent.indexOf('Edge') != -1
const isIE = window.navigator.userAgent.indexOf('Trident') != -1 && !isEdge

etc.

Each browser has a distinct user agent you can check.

These can be faked by the client of course, but in my opinion, are a more reliable long term solution.

1 Comment

You can't directly use this as navigator has to run only on/after the DOM render.
1

You can write test for IE like this.

<script>
     // Internet Explorer 6-11
          const isIE = document.documentMode;
          if (isIE){
            window.alert(
              "Your MESSAGE here."
            )
          }
</script>

Comments

1

This almost broke me, but I found something which seems pretty simple and straight forward, use the vendor name. ie. Google, Apple etc. navigator.vendor.includes('Apple') I hope this helps someone out there.

2 Comments

Opera now uses Chromium, so the vendor shows up as Google Inc. as well.
Firefox shows an empty string, so this is wrong
1

You can try this:

navigator.browserDetection= (function(){
    var ua= navigator.userAgent, tem, 
    M= ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
    if(/trident/i.test(M[1])){
        tem=  /\brv[ :]+(\d+)/g.exec(ua) || [];
        return 'IE '+(tem[1] || '');
    }
    if(M[1]=== 'Chrome'){
        tem= ua.match(/\b(OPR|Edge)\/(\d+)/);
        if(tem!= null) return tem.slice(1).join(' ').replace('OPR', 'Opera');
    }
    M= M[2]? [M[1], M[2]]: [navigator.appName, navigator.appVersion, '-?'];
    if((tem= ua.match(/version\/(\d+)/i))!= null) M.splice(1, 1, tem[1]);
    return M.join(' ');
})();

console.log(navigator.browserDetection); // outputs: `Chrome 92`

Comments

0

There is a new package that takes care of this for React: https://www.npmjs.com/package/react-browser-navigator

This is how you can use it:

// import the module
import useNavigator from "react-browser-navigator";

function App() {
  // importing the property
  let { userAgent } = useNavigator();

  // you can use it within the useEffect hook OR simply print the 
  // string into the return statement
  useEffect(() => {
    if (!isNull(userAgent)) {
      // printing out the entire object
      console.log("userAgent", userAgent);
    }
  }, [userAgent]);

  return (
    <div>
      <span>userAgent:</span> {userAgent}
    </div>
  );
}

Essentially, the output will be something like this:

Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36

1 Comment

I updated the content...
-1

This is all information you can get from your the browser of you client (using react):

    let latitude
    let longitude
    const location = window.navigator && window.navigator.geolocation

    if (location) {
      location.getCurrentPosition(position => {
        latitude = position.coords.latitude
        longitude = position.coords.longitude
      })
    }

    var info = {
      timeOpened: new Date(),
      timezone: new Date().getTimezoneOffset() / 60,
      pageon: window.location.pathname,
      referrer: document.referrer,
      previousSites: window.history.length,
      browserName: window.navigator.appName,
      browserEngine: window.navigator.product,
      browserVersion1a: window.navigator.appVersion,
      browserVersion1b: navigator.userAgent,
      browserLanguage: navigator.language,
      browserOnline: navigator.onLine,
      browserPlatform: navigator.platform,
      javaEnabled: navigator.javaEnabled(),
      dataCookiesEnabled: navigator.cookieEnabled,
      dataCookies1: document.cookie,
      dataCookies2: decodeURIComponent(document.cookie.split(';')),
      dataStorage: localStorage,
      sizeScreenW: window.screen.width,
      sizeScreenH: window.screen.height,
      sizeDocW: window.document.width,
      sizeDocH: window.document.height,
      sizeInW: window.innerWidth,
      sizeInH: window.innerHeight,
      sizeAvailW: window.screen.availWidth,
      sizeAvailH: window.screen.availHeight,
      scrColorDepth: window.screen.colorDepth,
      scrPixelDepth: window.screen.pixelDepth,
      latitude,
      longitude
    }
    console.log(info)

The browser is browserName

4 Comments

Even though I am using Chrome but it still says Netscape for window.navigator.appName
Same result for Firefox, Edge and IE
right.. I founded chrome in: "browserVersion1a": "5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36" and "browserVersion1b": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36"
Thanks, I know that is informative, but I dont think this will be helpful. Since you will have to do a lot of parsing to get the name out. Plus if they decided to change the format it will stop working. I am going to stick with @Shawn Matthews's answer for now.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.