Usando a API de contexto no React para criar um design de aplicativo responsivo

Olá, este artigo é uma continuação deste post , onde decidi iniciar uma série de pequenos tutoriais sobre a criação de um kit de interface do usuário. Ele descreve como usar o contexto para criar um tema de aplicativo. Hoje, quero complementar o aplicativo com outro contexto que nos ajude a mostrar os componentes da interface do usuário, com base no dispositivo do usuário.

imagem

Neste exemplo, também usarei o módulo create-react-context .

A árvore de tarefas será idêntica à anterior. Vamos nomear a nova pasta de contexto de mídia .

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

Lidamos rapidamente com os índices .

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
Como antes, crie createContext ( módulo npm ).

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

Importamos, desestruturamos e exportamos os componentes resultantes.

media-context / constants.js
Salve as variáveis ​​aqui.

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

Em uma abordagem adaptativa, o usuário usa principalmente 4 tipos de dispositivos - desktop, tablet, aplicativo móvel e nativo (nativo). Outros dispositivos possíveis: smart TV, relógio, etc. Neste exemplo, usaremos apenas dispositivos móveis e computadores .

theme-context / MediaProvider / MediaProvider.js
Como já sabemos, o Provider está disponível no React.Context , que "alimenta" os consumidores com o contexto. Isso lhes permite ouvir e responder a contextos em mudança.

Os acessórios do são device e touchable . Deixe-me lembrá-lo de que todos os valores passados ​​para o provedor de value estarão disponíveis para os consumidores.

 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

Uma descrição da funcionalidade do consumidor pode ser encontrada no artigo anterior, mas, resumindo, o Consumer responde ao contexto e retorna um novo componente.

Nesse caso, passamos dois parâmetros para children : o tipo de dispositivo e se o dispositivo é sensível ao toque.

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

Agora, um novo contexto está disponível em nosso aplicativo, vamos usá-lo.

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

Para usar o concurso de mídia, precisamos de um detector de mídia (para obter informações sobre o dispositivo do usuário). Não há detector de mídia em nosso aplicativo, então vamos levá-lo daqui - react -device-detect , ou seja, a flag isMobile .

Assim como no tema contextual, envolveremos nosso componente de teste em um provedor de mídia. O valor dos acessórios que o provedor passa para sua conta será invejado pelo dispositivo do cliente. Fui de um celular, enviamos uma versão móvel do site, de um computador - desktop. O código de trabalho pode ser encontrado aqui .

Para ver a diferença, siga o link em um navegador para computador e celular.

Isso é tudo! Agora, nosso aplicativo possui dois contextos que nos ajudarão a criar componentes mais versáteis e flexíveis em nosso UI-Kit. No próximo post, tentarei criar um componente complexo usando os dois contextos. Espero que você ache o artigo útil.

Obrigada

Source: https://habr.com/ru/post/pt463597/


All Articles