简体   繁体   中英

Render component in different order depending on screen-size (React)

I'm trying to work out how I would render a component differently in mobile view (I would like it to appear before my header in mobile, but after otherwise)

The code I have at the minute is

import React from 'react';
import NavigationBar from './NavigationBar';
import SiteHeader from './SiteHeader';

export default class App extends Component {

  constructor(props) {
     super(props);
     let width = window.innerWidth;
     if (width > 768) {
       this.setState(renderComponent =
         `<div className="container">
           <NavigationBar />
           <SiteHeader />
           {this.props.children}
         </div>`
       );
     } else {
       this.setState(renderComponent =
         `<div className="container">
           <NavigationBar />
           <SiteHeader />
           {this.props.children}
         </div>`
       );
     }
   }

  render() {

    return (
      {renderComponent}
    );
  }

}

However this is not working (Component is not defined), I figured I couldn't just set the component as strings but hopefully this is enough info for any suggestions on the correct way to do it

Thanks!

Your code has several issues, see comments for more details:

export default class App extends Component {

  constructor(props) {
     super(props);
     // typo: use `=` instead of `:`
     let width = window.innerWidth;
     // dont use setState in constructor, initialize state instead
     this.state = {};
     if (width > 768) {
       // set renderComponent property according to window size
       // components are declared using JSX, not string (do not use ``)
       this.state.renderComponent = (
         <div className="container">
           <NavigationBar />
           <SiteHeader />
           {this.props.children}
         </div>
       );
     } else {
       this.state.renderComponent = (
         <div className="container">
           <NavigationBar />
           <SiteHeader />
           {this.props.children}
         </div>
       );
     }
   }

  render() {
    // access state through `this.state`
    // you don't need {} while it is not inside JSX
    return this.state.renderComponent;
  }

}

Furthermore I would move this logic to the render method, don't use state to store components but render it directly. For example:

export default class App extends Component {

  render() {
     let width = window.innerWidth;
     if (width > 768) {
       return (
         <div className="container">
           <NavigationBar />
           <SiteHeader />
           {this.props.children}
         </div>
       );
     } else {
       return (
         <div className="container">
           <NavigationBar />
           <SiteHeader />
           {this.props.children}
         </div>
       );
     }
  }

}

I think you should have your rendering logic in render() method. You could use matchMedia() to render components differently based on resolution or orientation - similarly as when using media queries.

https://developer.mozilla.org/pl/docs/Web/API/Window/matchMedia

You can try this:

componentWillMount = () => {
            let mql = window.matchMedia("all and (max-width: 767px)")
            if (mql.matches) { // if media query matches
                document.body.style.backgroundColor = "#fff";
            } else {
                document.body.style.backgroundColor = "#2d74da";
            }
        }
    componentWillUnmount = () => {
            document.body.style.backgroundColor = null;
        }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM