Using Context API in React to create responsive application design

Hi, this article is a continuation of this post , where I decided to start a series of small tutorials on creating a UI-Kit. It describes how to use context to create an application theme. Today I want to supplement the application with another context that will help us show the components of the UI, based on the user's device.



image



In this example, I will also use the create-react-context



module.



The task tree will be identical to the previous one. Let's name the new media-context folder.



 media-context/ MediaConsumer/ MediaConsumer.js index.js MediaProvider/ MediaProvider.js index.js constants.js context.js index.js
      
      





We’ll quickly deal with indexes .



media-context / index.js

 export { MediaProvider } from './MediaProvider'; export { MediaConsumer } from './MediaConsumer';
      
      





theme-context / MediaConsumer / index.js

 export { MediaConsumer } from './MediaConsumer';
      
      





theme-context / MediaProvider / index.js

 export { MediaProvider } from './MediaProvider';
      
      





theme-context / context.js

As before, create createContext



( npm module ).



 import createContext from 'create-react-context'; const { Provider, Consumer } = createContext(); export { Provider, Consumer };
      
      





We import, destructure and export the resulting components.



media-context / constants.js

Save the variables here.



 export const devices = ["mobile", "tablet", "desktop", "native"]; export const defaultDevice = "mobile";
      
      





In an adaptive approach, the user mainly uses 4 types of devices - desktop, tablet, mobile and native application (native). Other possible devices: smart TV, clock, etc. In this example, we will use only mobile & desktop .



theme-context / MediaProvider / MediaProvider.js

As we already know, Provider is available in React.Context



, which feeds consumers with context. It allows them to listen and respond to changing contexts.







Props are device



and touchable



. Let me remind you that all the values ​​passed to the value



provider will become available to consumers.



 import React from "react"; import PropTypes from "prop-types"; import { Provider } from "../context"; import { devices, defaultDevice } from "../constanst"; function MediaProvider(props) { const device = devices.includes(props.device) ? props.device : props.defaultDevice; return <Provider value={{ ...props, device }}>{props.children}</Provider>; } MediaProvider.propTypes = { device: PropTypes.oneOf(devices), touchable: false, children: PropTypes.node }; MediaProvider.defaultProps = { device: defaultDevice, touchable: false }; export { MediaProvider };
      
      





theme-context / MediaConsumer / MediaConsumer.js



A description of the functionality of the consumer can be found in the previous article, but in short, Consumer



responds to the context and returns a new component.



In this case, we pass two parameters to children



: the type of device and whether the device is touch-sensitive.



 import React from "react"; import PropTypes from "prop-types"; import { defaultTo } from "lodash"; import { devices, defaultDevice } from "../constanst"; import { Consumer } from '../context'; function MediaConsumer(props) { return ( <Consumer> {media => props.children({ touchable: defaultTo(media.touchable, props.defaultTouchable), device: defaultTo(media.device, props.defaultDevice), })} </Consumer> ) } MediaConsumer.propTypes = { defaultTouchable: PropTypes.bool, defaultDevice: PropTypes.oneOf(devices), children: PropTypes.func.isRequired }; MediaConsumer.defaultProps = { defaultDevice, defaultTouchable: false }; export { MediaConsumer };
      
      





Now a new context is available in our application, let's use it.



 import React from "react"; import ReactDOM from "react-dom"; import { isMobile } from "react-device-detect"; import cx from "classnames"; import { ThemeConsumer, ThemeProvider } from "./theme-context"; import { MediaConsumer, MediaProvider } from "./media-context"; import "./styles.css"; function renderSVG({ device, touchable }) { if (device === "mobile" && touchable) { return "https://image.flaticon.com/icons/svg/124/124114.svg"; } if (device === "tablet" && touchable) { return "https://image.flaticon.com/icons/svg/124/124099.svg"; } if (device === "desktop") { return "https://image.flaticon.com/icons/svg/124/124092.svg"; } } function MyComponent() { const renderMyComponent = (theme, media) => { const myComponentClassName = cx("my-class", { "my-class-dark": theme === "dark", "my-class-light": theme === "light" }); return ( <div className="wrapperDiv"> <object className={myComponentClassName} data={renderSVG(media)} type="image/svg+xml" /> </div> ); }; return ( <MediaConsumer> {media => ( <ThemeConsumer> {theme => renderMyComponent(theme, media)} </ThemeConsumer> )} </MediaConsumer> ); } function App() { return ( <MediaProvider device={isMobile ? "mobile" : "desktop"} touchable={isMobile} > <ThemeProvider theme="light"> <MyComponent /> </ThemeProvider> </MediaProvider> ); } const rootElement = document.getElementById("root"); ReactDOM.render(<App />, rootElement);
      
      





To use the media contest, we need a media detector (to obtain information about the user’s device). There is no media detector in our application, so let's take it from here - react-device-detect , namely the isMobile flag.



As with the contextual theme, we will wrap our test component in a media provider. The value of the props that the provider passes to his account will be envy of the client’s device. I went in from a mobile, we send a mobile version of the site, from a computer - desktop. The working code can be found here .



To see the difference, follow the link from a desktop and mobile browser.



Everything! Now our application has two contexts that will help us create more versatile and flexible components in our UI-Kit. In the next post I will try to create a complex component using both contexts. I hope you find the article helpful.



Thank.



All Articles