How to check if React app is being viewed on Desktop or Mobile

5.8k views Asked by At

Making a React App and need to have different functionality for Desktop and Mobile. So far I did this:

const [width, setWidth] = useState(window.innerWidth);
const [mobile, setMobile] = useState(false);

const handleWindowSizeChange = () => {
        setWidth(window.innerWidth);
        if(width <= 500) {
            setMobile(true);
        } else setMobile(false);
    }

    useEffect(() => {
        window.addEventListener('resize', handleWindowSizeChange);
        return () => {
            window.removeEventListener('resize', handleWindowSizeChange);
        }
    }, []);

But it's not working. I console logged the "mobile" state and it always logs "false" even tho i change the screen size in my browser. Especially if i reload my page while still being in mobile view. How do I make it work?

2

There are 2 answers

0
Andrew Hunt On BEST ANSWER

It looks like there are two issues preventing this from working.

  1. You're not setting isMobile to the correct value on initial page load. The handler looks reasonable for updating isMobile on resize, but if the window isn't resized, it won't be set correctly.
  2. Within handleWindowSizeChange, you're using width, which hasn't been set to window.innerWidth yet.

My recommendation would be to get rid of the width state (unless you need it outside of getting isMobile). Your code could look something like:

const [mobile, setMobile] = useState(window.innerWidth <= 500);

const handleWindowSizeChange = () => {
  setMobile(window.innerWidth <= 500);
}

useEffect(() => {
  window.addEventListener('resize', handleWindowSizeChange);
  return () => {
    window.removeEventListener('resize', handleWindowSizeChange);
  }
}, []);
0
Baran On

Andrew Hunt's solution returns an error with Next.js.

error - ReferenceError: window is not defined

The reason is by default Next.js does server-side rendering. This means that the content will be rendered before accessing the browser. Since the browser is not used while rendering the content, window of the browser will not be defined.

To overcome this, we can check if it's in mobile view once window is defined.

const [isMobile, setIsMobile] = useState(
    typeof window !== 'undefined' && window.innerWidth < 1024
  );

  useEffect(() => {
    function handleResize() {
      setIsMobile(window.innerWidth < 1024);
    }

    if (typeof window !== 'undefined') {
      handleResize();
    }

    window.addEventListener('resize', handleResize);
    return () => {
      // remove event listener when the component is unmounted to not cause any memory leaks
      // otherwise the event listener will continue to be active
      window.removeEventListener('resize', handleResize);
    };
  // add `isMobile` state variable as a dependency so that
  // it is called every time the window is resized
  }, [isMobile]);