Usando a API de contexto no React para criar um tema de aplicativo global

Olá, este é o meu primeiro post no Habr. Espero que você esteja interessado.

Então, quero iniciar uma série de postagens direta ou indiretamente relacionadas à criação do ui-kit.

imagem

O objetivo desta publicação: Encontre uma solução para controlar o tema de um aplicativo cujos componentes são implementados no React.js . Usaremos dois temas globais - escuro e claro .

Neste exemplo, usarei o módulo create-react-context para criar o contexto.

Começamos criando uma pasta na raiz do projeto ( src / ) chamada theme-context . A estrutura desta pasta ficará assim:

 theme-context/ ThemeConsumer/ ThemeConsumer.js index.js ThemeProvider/ ThemeProvider.js index.js constants.js context.js index.js 

Pessoalmente, eu sempre começo com o arquivo index.js . Você faz todas as importações e exportações no início e, em seguida, sua cabeça não faz mal a elas.

theme-context / index.js

 export { ThemeProvider } from './ThemeProvider'; export { ThemeConsumer } from './ThemeConsumer'; 

theme-context / ThemeConsumer / index.js

 export { ThemeConsumer } from './ThemeConsumer'; 

theme-context / ThemeProvider / index.js

 export { ThemeProvider } from './ThemeProvider'; 

theme-context / context.js

Em seguida, criaremos um contexto usando createContext (desculpe o trocadilho), usando o módulo daqui .

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

Importe createContext , createContext -o em Provider and Consumer e exporte-os.

theme-context / constants.js

Tudo é simples aqui, criamos nossas variáveis ​​para não poluir os arquivos principais.

 export const themeLight = 'light'; export const themeDark = 'dark'; export const defaultTheme = themeLight; export const themes = [themeLight, themeDark]; 

Como eu disse anteriormente, nosso aplicativo terá dois temas - claro e escuro.

theme-context / ThemeProvider / ThemeProvider.js

Aqui falaremos sobre o provedor - o componente que está disponível em cada objeto React.Context . Permite que os consumidores escutem e respondam a contextos em mudança.

Em nosso exemplo, o suporte é um theme que será transferido para todos os fluxos de desse Provider a.

 import React from 'react'; import { Provider } from '../context'; import { defaultTheme, themes } from '../constants'; function ThemeProvider({ theme, children }) { return <Provider value={theme}>{children}</Provider>; } export { ThemeProvider }; 

theme-context / ThemeConsumer / ThemeConsumer.js

Neste arquivo, trabalharemos com o Consumidor - este é um componente que "escuta, espera" por uma mudança de contexto. O filho deste componente é uma função. Esta é uma obrigação ao usar o Consumer .

Esta função recebe os valores do contexto atual e retorna um React Node , em outras palavras, um componente.

A partir da documentação: o valor do argumento (no nosso caso {theme => / * para visualizar algo com base no valor do contexto * /}) será igual ao theme props theme pai mais próximo na árvore do Provider para este contexto.

 import React from 'react'; import { defaultTo } from 'lodash'; import { Consumer } from '../context'; import { defaultTheme, themes } from '../constants'; function ThemeConsumer(props) { return <Consumer>{theme => props.children(defaultTo(theme, props.defaultTheme))}</Consumer>; } export { ThemeConsumer }; 

Aqui vale a pena prestar atenção ao seguinte:
Se o tema não foi selecionado explicitamente, precisamos que o tema do componente seja selecionado automaticamente. Para isso, uso o lodash - defaultTo . No entanto, essa funcionalidade pode ser alcançada de várias outras maneiras.

Isso é tudo, o contexto do tema está pronto para uso!

Vamos ver como aplicá-lo. Vamos criar um componente simples que escute e responda ao contexto de nosso aplicativo.

 .my-class { font-family: sans-serif; text-align: center; font-size: 30px; } .my-class-light { color: #39cccc; } .my-class-dark { color: #001a33; } 

 import React from "react"; import ReactDOM from "react-dom"; import cx from "classnames"; import { ThemeConsumer, ThemeProvider } from "./theme-context"; import "./styles.css"; function MyComponent() { const renderMyComponent = theme => { const myComponentClassName = cx("my-class", { "my-class-dark": theme === "dark", "my-class-light": theme === "light" }); return ( <div className={myComponentClassName}> <h1>    </h1> </div> ); }; return <ThemeConsumer>{theme => renderMyComponent(theme)}</ThemeConsumer>; }; function App() { return ( <MyComponent /> ); } const rootElement = document.getElementById("root"); ReactDOM.render( //      theme  dark <ThemeProvider theme="light"> <App /> </ThemeProvider> , rootElement); 

Então, envolvemos nosso <App /> no provedor e agora o tema ficou disponível para todos os componentes-consumidores em nosso aplicativo. Em seguida, <App /> retorna <MyComponent /> , este é , e ele criará nosso componente e passará o tema do nosso aplicativo. E já tendo um tópico como argumento:

 <ThemeConsumer>{theme => renderMyComponent(theme)}</ThemeConsumer> 

podemos usá-lo ao criar um componente
  const renderMyComponent = theme => { //      }; 

O código de trabalho pode ser encontrado aqui .

É isso, espero que você ache este post útil. Na próxima postagem, tentarei criar um contexto de mídia , cuja funcionalidade nos ajudará a visualizar os componentes no equipamento do dispositivo do usuário.

Obrigada

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


All Articles