Utilisation de l'API contextuelle dans React pour créer un thème d'application global

Salut, c'est mon premier post sur Habr. J'espère que cela vous intéressera.

Donc, je veux commencer une série de postes directement ou indirectement liés à la création de ui-kit.

image

L'objectif de ce billet: Trouver une solution pour contrôler le thème d'une application dont les composants sont implémentés dans React.js . Nous utiliserons deux thèmes globaux - l' obscurité et la lumière .

Dans cet exemple, j'utiliserai le module create-react-context pour créer le contexte.

Nous commençons par créer un dossier à la racine du projet ( src / ) appelé theme-context . La structure de ce dossier ressemblera à ceci:

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

Personnellement, je commence toujours par le fichier index.js . Vous faites toutes les importations et exportations au début, puis votre tête ne leur fait pas de mal.

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

Ensuite, nous allons créer un contexte en utilisant createContext (désolé pour le jeu de mots), en utilisant le module d'ici .

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

Importez createContext , détruisez-le dans Provider et Consumer et exportez-les.

theme-context / constants.js

Tout est simple ici, nous créons nos variables pour ne pas polluer les fichiers principaux.

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

Comme je l'ai dit plus tôt, notre application aura deux thèmes - clair et foncé.

theme-context / ThemeProvider / ThemeProvider.js

Ici, nous parlerons du fournisseur - le composant qui est disponible dans chaque objet React.Context . Il permet aux consommateurs d'écouter et de réagir à des contextes changeants.

Dans notre exemple, l'accessoire est un theme qui sera transféré à tous les flux de ce 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

Dans ce fichier, nous travaillerons avec Consumer - il s'agit d'un composant qui «écoute, attend» un changement de contexte. L'enfant de ce composant est une fonction. C'est un must lors de l'utilisation de Consumer .

Cette fonction reçoit les valeurs du contexte actuel et renvoie un React Node , en d'autres termes, un composant.

D'après la documentation: la valeur de l'argument (dans notre cas {theme => / * pour visualiser quelque chose en fonction de la valeur de contexte * /}) sera égale au theme accessoires theme parent theme plus proche dans l'arborescence du Provider pour ce contexte.

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

Ici, il convient de prêter attention aux éléments suivants:
Si le thème n'a pas été explicitement sélectionné, nous avons besoin que le thème du composant soit sélectionné automatiquement, pour cela j'utilise l' lodash de lodash - defaultTo . Cependant, cette fonctionnalité peut être obtenue de nombreuses autres manières.

C'est tout, le contexte du thème est prêt à l'emploi!

Voyons comment l'appliquer. Créons un composant simple qui écoutera et répondra au contexte de notre application.

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

Nous avons donc enveloppé notre <App /> dans le fournisseur, et maintenant le thème est devenu disponible pour tous les consommateurs de composants dans notre application. Ensuite, <App /> renvoie <MyComponent /> , c'est , et il créera notre composant et lui passera le thème de notre application. Et ayant déjà un sujet en argument:

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

nous pouvons l'utiliser lors de la création d'un composant
  const renderMyComponent = theme => { //      }; 

Le code de travail peut être trouvé ici .

C'est tout, j'espère que ce billet vous sera utile. Dans le prochain article, je vais essayer de créer un contexte multimédia , dont la fonctionnalité nous aidera à visualiser les composants sur l'équipement de l'appareil de l'utilisateur.

Je vous remercie

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


All Articles