React-responsive: Conditional rendering of components

Siddhartha Chowdhury
applike
Published in
4 min readAug 22, 2019

--

This article is about rendering React components based on the current device (or based on the viewport). Let’s say we need to display component <SideNav/> when on the desktop but component <TopNav/> on mobile.
This can be achieved through conditional rendering of React components. We all know what conditional rendering is in React.js, but I am here to share my experience in dealing with detecting the viewport BEFORE conditional rendering.

If you are just here for the solution — check out the NPM packages —

Our Goal

In the end, we should be able to render React components conditionally, as shown below. Note that we will use placeholders for the TopNav and SideNav components:

Conditional rendering of react-component
<Responsive 
displayIn={[
"Laptop"
]}>
<SideNav />
</Responsive>
<Responsive
displayIn={[
"Tablet",
"Mobile"
]}
>
<TopNav />
</Responsive>

Here, I am sharing the working example of this project in codesandbox, for better understanding —
https://codesandbox.io/s/friendly-breeze-72tel

Our small project

Step 1: Get all the breakpoints in an object. Please note that these values were derived from chrome’s developer tool:

export const DeviceWidthObject = {  MobileSmall      : { max: 320, min: 0 },
MobileMedium : { max: 375, min: 321 },
MobileLarge : { max: 767, min: 376 },
Tablet : { max: 991, min: 768 }, LaptopSmall : { max: 1024, min: 992 },
LaptopLarge : { max: 1440, min: 1025 },
LargerThanLaptop : { max: 2560, min: 1441 },
LargeScreenMax : { max: 999999, min: 2561 }
};export const IdDeviceBreakpointsByWidth = {
laptop_max : 1440,
laptop_min : 992,
tablet_min : 768,
tablet_max : 991,
mobile_max : 767,
default_min : 768 // Unrecognized device
}
export const IdMobileHeight = {
mobileLandscape_min : 320,
mobileLandscape_max : 425
}

Step 2: Get the current window dimension function. This function will help in getting the current viewport size through which we can derive the device type:

export const getWindowDimension = () => {const width = window.innerWidth 
|| document.documentElement.clientWidth
|| document.body.clientWidth;
const height = window.innerHeight
|| document.documentElement.clientHeight
|| document.body.clientHeight;
return {width, height}};

Step 3: This is going to be a massive function which derives the device type. I know it’s a big function, but it’s very simple, mostly chunks of if-else blocks:

utilResponsive.ts

> Please note: Up until now, you can pull all the above code in a single file, say utilResponsive.js

Also, there is another thing to note in the above code block — the handleExceptions() function. This is a special function which is checked before the main function is run. At the moment it only detects iPad Pro as its screen size is as big as a laptop screen.

Step 4: Lastly, we need to create a React component which we can import and implement the conditional rendering. This file can be named - Responsive.js :

import React from 'react'
import {
getWindowDimension,
IdDeviceBreakpointsByWidth,
IdMobileHeight
} from './utilResponsive'
const { width, height } = getWindowDimension()
const initialState = { width, height }
export class Responsive extends React.PureComponent {
state = initialState
componentDidMount () {
window.addEventListener('resize', this.handleResize, false)
}
componentWillUnmount () {
window.removeEventListener('resize', this.handleResize, false)
}
render = () => {
const { children, displayIn } = this.props
const { width, height } = this.state
const shouldRenderChildren = this.shouldRender(displayIn, width, height)
return (
<React.Fragment>
{shouldRenderChildren ? children : null}
</React.Fragment>
)
}
handleResize = () => {
const { width, height } = getWindowDimension()
this.setState({ width, height })
}
shouldRender = (display, width, height) => {
if (
display.indexOf('Laptop') !== -1 &&
width >= IdDeviceBreakpointsByWidth.laptop_min
) {
return true
}
if (
display.indexOf('Tablet') !== -1 &&
(width <= IdDeviceBreakpointsByWidth.tablet_max &&
width >= IdDeviceBreakpointsByWidth.tablet_min)
) {
return true
}
// For mobile regardless of orientation
if (
display.indexOf('Mobile') !== -1 &&
width <= IdDeviceBreakpointsByWidth.mobile_max
) {
return true
}
if (
display.indexOf('MobilePortrait') !== -1 &&
(width <= IdDeviceBreakpointsByWidth.mobile_max &&
height >= IdMobileHeight.mobileLandscape_max)
) {
return true
}
return !!(
display.indexOf('MobileLandScape') !== -1 &&
(width <= IdDeviceBreakpointsByWidth.mobile_max &&
height <= IdMobileHeight.mobileLandscape_min)
)
}
}

And that’s it! Our tiny little project is complete. Now to see it in action:

  1. Import the Responsive React component we just created above in your container component (where you want to have the conditional rendering).
  2. Use it as follows:
<>
<Responsive displayIn={["Laptop"]}>
<SideNav />
</Responsive>
<Responsive displayIn={["Mobile"]>
<TopNav />
</Responsive>
</>

Wrapping up

I hope all of the above makes sense. Please comment if you liked it or if it can be improved.

In case if you are looking for new challenges or a really exciting place to work, check out our open positions at Applike. We are hiring!

You will find the code here — https://github.com/applike/react-responsive
and a working example here — https://codesandbox.io/s/friendly-breeze-72tel

Thanks!

--

--