38

This should be an easy one for you React monsters. :) I have the condition written but I can't figure out how to handle the viewport size in my constructor for the condition to work. Plain and simple, I want to show one element when the viewport size is 1451px or wider and another when 1450px or smaller.

This is my code (simplified)

class My Class extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            isDesktop: "1450px" //This is where I am having problems
        };
    }

    render() {
        const isDesktop = this.state.isDesktop;

        return (
            <div>
                {isDesktop ? (
                    <div>I show on 1451px or higher</div>
                ) : (
                    <div>I show on 1450px or lower</div>
                )}
            </div>
        );
    }
}

Perhaps I am suppposed to work it with ComponentWillMount or ComponentDidMount. Honestly, not sure. I'm new with React.

Thanks in advance guys.

LOTUSMS
  • 10,317
  • 15
  • 71
  • 140
  • Do you want to update `isDesktop` on page resize? – Kristaps Taube Oct 05 '17 at 13:05
  • ummm, good question. I would say yes. As the user resizes, when the width falls under 1450px wide, it should render the correct component. I'm trying to workout responsiveness without CSS – LOTUSMS Oct 05 '17 at 13:16

5 Answers5

58

Perhaps I am suppposed to work it with ComponentWillMount or ComponentDidMount

Yes, you need to listen for resize event and update internal state on change. You can do it by adding event handler when component mounts. Try full example here.

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isDesktop: false //This is where I am having problems
    };

    this.updatePredicate = this.updatePredicate.bind(this);
  }
  componentDidMount() {
    this.updatePredicate();
    window.addEventListener("resize", this.updatePredicate);
  }

  componentWillUnmount() {
    window.removeEventListener("resize", this.updatePredicate);
  }

  updatePredicate() {
    this.setState({ isDesktop: window.innerWidth > 1450 });
  }

  render() {
    const isDesktop = this.state.isDesktop;

    return (
      <div>
        {isDesktop ? (
          <div>I show on 1451px or higher</div>
        ) : (
          <div>I show on 1450px or lower</div>
        )}
      </div>
    );
  }
}
Kristaps Taube
  • 2,363
  • 1
  • 17
  • 17
  • That was Gold! I understand the concept now. I should be able to use this concept in other conditions I have to work out. Thanks! – LOTUSMS Oct 05 '17 at 13:30
  • Good answer, thoroughly shows the architecture of a conditional state change. – serraosays Jul 11 '19 at 20:42
34

Just to post a recent update here after I had the same issue, but set it up using a functional component and the useEffect / useState React Hooks:

const MyFunction = () => {
  const [isDesktop, setDesktop] = useState(window.innerWidth > 1450);

  const updateMedia = () => {
    setDesktop(window.innerWidth > 1450);
  };

  useEffect(() => {
    window.addEventListener("resize", updateMedia);
    return () => window.removeEventListener("resize", updateMedia);
  });

  return (
    <div>
      {isDesktop ? (
        <div>I show on 1451px or higher</div>
      ) : (
        <div>I show on 1450px or lower</div>
      )}
    </div>
  );
}
foakesm
  • 803
  • 10
  • 18
13

if you use NextJS ... you will have an error like : window is not defined. Here is the code with no error, enjoy.

First i check if the size of the window if more or less 1450px( because if the user never resize the window all the code will be useless )

But i also need to check if the user resize the window ... see by yourself

    export default function MyFunction() {
        const [isDesktop, setDesktop] = useState(false);

  useEffect(() => {
    if (window.innerWidth > 1450) {
      setDesktop(true);
    } else {
      setDesktop(false);
    }

    const updateMedia = () => {
      if (window.innerWidth > 1450) {
        setDesktop(true);
      } else {
        setDesktop(false);
      }
    };
    window.addEventListener('resize', updateMedia);
    return () => window.removeEventListener('resize', updateMedia);
  }, []);
    
      return (
          <div>
              {isDesktop ? (
                  <div>I show on 1451px or higher</div>
              ) : (
                  <div>I show on 1450px or lower</div>
              )}
          </div>
      );
    }
sylvain s
  • 324
  • 4
  • 11
  • Awesome solution! – Marcelo Melo May 25 '22 at 19:57
  • Thanks for the solution. But instead of repating "window size comparision code" you can just call updateMedia() (after the function is defined in side the useEffect) You already have this code inside the updateMedia function. – freewill Feb 27 '23 at 20:34
4

the issue with your code is that it only works if the resizing happens, here I have the handleWindowResiz function will set the width to the window.innerWidth and compares it to the breakPoint to conditionally render your UI, if the user resizes the screen the event listener will be triggered and the handleWindowResiz will be called and it will reset the width to the new window.innerWidth and you get your desired UI. So the UI is always rendered correctly when the component is first rendered and when the user resizes the screen width.

const MyFunction = () => {

  const [width, setWidth] = React.useState(window.innerWidth);
  const breakPoint = 1450;

 

  useEffect(() => {
   const handleWindowResize = () => setWidth(window.innerWidth);
   window.addEventListener("resize", handleWindowResize);

    
   return () => window.removeEventListener("resize", handleWindowResize);
  },[]);

  return (
    <div>
      {width > breakPoint? (
        <div>I show on 1451px or higher</div>
      ) : (
        <div>I show on 1450px or lower</div>
      )}
    </div>
  );
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
ahlambey
  • 41
  • 1
  • 4
  • 1
    It would be nice if you explain what are you doing with your code. – Gary Strivin' Dec 17 '20 at 17:09
  • when the component is rendered in the first time the handleWindowResize function will set the initial width and then we compare the width with the breakPoint to chose what should be rendered
    I show on 1451px or higher
    or
    I show on 1450px or lower
    , and when the window is resized the event listener will be triggered and the width will be reset to the new window width. so what is different here is even when the component is first rendered we can get the window width and do our conditional rendering. I hope I was able to explain myself well :)
    – ahlambey Dec 17 '20 at 17:21
  • Please put the explanation in the *answer*, not in a comment. – Adrian Mole Dec 17 '20 at 17:47
1
class My Class extends React.Component {
  constructor(props) {
      super(props);
      this.state = {
          isDesktop: window.innerHeight > 1450,
      };
  }

  render() {
      const isDesktop = this.state.isDesktop;

      return (
          <div>
              {isDesktop ? (
                  <div>I show on 1451px or higher</div>
              ) : (
                  <div>I show on 1450px or lower</div>
              )}
          </div>
      );
  }}

Here more info Get viewport/window height in ReactJS

bobu
  • 908
  • 8
  • 14
  • It didn't work unfortunately, also the innerHeight caught my attention. Aren't you handling the Height instead of the width? I mean to handle the width of the viewport. I tried innerWidth and it didn't work either. I haven't checked the link you provided though – LOTUSMS Oct 05 '17 at 13:14
  • You can create resize listener, with callback function where you can change state of isDesktop, currentlly this implementation work only on refreshing page – bobu Oct 05 '17 at 13:21