How can I hide a component in React depending on the screen size?

Viewed 7737

I'm trying to hide a Carousel component when the screen is mobile only and display it in tablets or larger screens. What would be the best way? I'm using bootstrap.

Below is an edited version of my code for simplicity's sake. As you can see, this is my home page and is at the top. I want this to be hidden in the mobile version. Thanks for your help!

import React from 'react'
import { Container, Row, Col } from 'react-bootstrap';
import { HomeStyled } from './style';
import HomePageCarousel from '../Carousel';



const Home = () => {
    
    return (
    <>    
        **<HomePageCarousel/>**
        <HomeStyled>
            <Container fluid>
            <Row>
                <Col>   
                </Col> 
            </Row>
            <Row>
            </Row>
            </Container>
        </HomeStyled>
    </>
    )
}

export default Home;

Below is the CSS, where I am using styled-components..

import styled from 'styled-components';

export const HomeStyled = styled.section`

@media screen and (min-width: 320px) and (max-width: 576px) {
    img,
    p   {
        display: none;
    }
}

.left-alignment {
        display: flex;
        flex-direction: column;
        margin-top: 140px;
    }    

img {
    height: 300px;
    margin: auto;
}

.right-alignment {
    display: flex;
    flex-direction: row;
    justify-content: flex-end;
    align-items: flex-end;
    font-size: 1.2rem;
    font-weight: 400;
    margin: 0 auto;
}

.text-alignment {
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    align-items: flex-end;
    font-size: 1.2rem;
    font-weight: 400;
    margin-left: 50px;
    //margin: 0 auto;

}
5 Answers

Define useWindowSize.js custom hook to get the current window width/height

import { useState, useEffect } from "react";

// Hook
const useWindowSize = () => {
    // Initialize state with undefined width/height so server and client renders match
    // Learn more here: https://joshwcomeau.com/react/the-perils-of-rehydration/
    const [windowSize, setWindowSize] = useState({
        width: undefined,
        height: undefined
    });

    useEffect(() => {
        // only execute all the code below in client side
        if (typeof window !== "undefined") {
            // Handler to call on window resize
            function handleResize() {
                // Set window width/height to state
                setWindowSize({
                    width: window.innerWidth,
                    height: window.innerHeight
                });
            }

            // Add event listener
            window.addEventListener("resize", handleResize);

            // Call handler right away so state gets updated with initial window size
            handleResize();

            // Remove event listener on cleanup
            return () => window.removeEventListener("resize", handleResize);
        }
    }, []); // Empty array ensures that effect is only run on mount
    return windowSize;
};

export default useWindowSize;

in your code

import React from 'react'
import { Container, Row, Col } from 'react-bootstrap';
import { HomeStyled } from './style';
import HomePageCarousel from '../Carousel';

import useWindowSize from '.path/to/your/hooks/useWindowSize'

const Home = () => {
    
    const size = useWindowSize();    

    return (
    <>    
        {size.width > 600 && <HomePageCarousel/>}
        <HomeStyled>
            <Container fluid>
            <Row>
                <Col>   
                </Col> 
            </Row>
            <Row>
            </Row>
            </Container>
        </HomeStyled>
    </>
    )
}

export default Home;

The most efficient way to doing this is using the matchMedia API: https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia

In React it will look like this:

const useMatchMedia = (mediaQuery, initialValue) => {
  const [isMatching, setIsMatching] = useState(initialValue)
  useEffect(() => {
    const watcher = window.matchMedia(mediaQuery)
    setIsMatching(watcher.matches)
    const listener = (matches) => {
      setIsMatching(matches.matches)
    }
    if (watcher.addEventListener) {
      watcher.addEventListener('change', listener)
    } else {
      watcher.addListener(listener)
    }
    return () => {
      if (watcher.removeEventListener) {
        return watcher.removeEventListener('change', listener)
      } else {
        return watcher.removeListener(listener)
      }
    }
  }, [mediaQuery])

  return isMatching
}

and:

const isDesktopResolution = useMatchMedia('(min-width:992px)', true)

isDesktopResolution && (
  <YourComponents />
)

EDIT:

CodeSanbox

Your code will look like this:

import React from 'react'
import { Container, Row, Col } from 'react-bootstrap';
import { HomeStyled } from './style';
import HomePageCarousel from '../Carousel';


const isDesktopResolution = useMatchMedia('(min-width:992px)', true)

const Home = () => {
    
    return (
    <>    
        {isDesktopResolution && (
          <HomePageCarousel/>
        )}
        <HomeStyled>
            <Container fluid>
            <Row>
                <Col>   
                </Col> 
            </Row>
            <Row>
            </Row>
            </Container>
        </HomeStyled>
    </>
    )
}

export default Home;

In your (s)css:

@media (max-width: 600px) {
  .element-to-hide {
    display: none;
  }
}

More tricky one (detecting modern touch-like mobile devices):

@media only screen and (hover: none) and (pointer: coarse){
  .element-to-hide {
    display: none;
  }
}

Well there are many ways in which you can get the screen size and then based on that screen size you can conditionally render components

The easiest way you can get the screen width is :-

const Home = () => {

const isMobile = window.screen.width < 600

  return (
    <>
        { isMobile && < HomePageCarousel /> }

        ...rest of the code
    </>
  )

}

Remember when you will inspect this code in browser make sure to refresh after choosing mobile screen as this is not a state variable so it will not cause a re-render. But it will work fine when opened in a mobile device.

is there any other way, by using grid itself can we do? like fxLayout in angular we can hide and show div base on screen size.

Related