Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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!

like image 558
does_not_compute Avatar asked Nov 29 '22 13:11

does_not_compute


2 Answers

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>
       );
     }
  }

}
like image 68
madox2 Avatar answered Dec 05 '22 04:12

madox2


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

like image 23
macro Avatar answered Dec 05 '22 03:12

macro