Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React conditionally render based on viewport size

Tags:

reactjs

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.

like image 236
LOTUSMS Avatar asked Oct 05 '17 12:10

LOTUSMS


3 Answers

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>
    );
  }
}
like image 95
Kristaps Taube Avatar answered Nov 19 '22 03:11

Kristaps Taube


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>
  );
}
like image 30
foakesm Avatar answered Nov 19 '22 04:11

foakesm


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>
      );
    }
like image 12
sylvain s Avatar answered Nov 19 '22 02:11

sylvain s