在React中使用Context API创建全局应用程序主题

嗨,这是我在Habr上的第一篇文章。 希望您对此感兴趣。

因此,我想开始一系列与ui-kit的创建直接或间接相关的帖子。

图片

这篇文章的目的:找到一种解决方案来控制其组件在React.js中实现的应用程序的主题。 我们将使用两个全局主题- 黑暗光明

在此示例中,我将使用create-react-context模块创建上下文。

我们首先在项目的根目录( src / )中创建一个名为theme-context的文件夹。 该文件夹的结构如下所示:

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

就个人而言,我总是从index.js文件开始。 您从一开始就进行所有进出口,然后您的头就不会受到伤害。

主题上下文/ index.js

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

主题上下文/ ThemeConsumer / index.js

 export { ThemeConsumer } from './ThemeConsumer'; 

主题上下文/ ThemeProvider / index.js

 export { ThemeProvider } from './ThemeProvider'; 

主题上下文/context.js

接下来,我们将使用来自此处的模块使用createContext (双关语很抱歉)创建上下文。

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

导入createContext ,将其销毁为ProviderConsumer ,然后将其导出。

主题上下文/constants.js

这里的一切都很简单,我们创建变量以免污染主文件。

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

正如我之前所说,我们的应用程序将具有两个主题-浅色和深色。

主题上下文/ ThemeProvider / ThemeProvider.js

在这里,我们将讨论提供程序-每个React.Context对象中可用的组件。 它允许消费者聆听并响应不断变化的环境。

在我们的示例中, 道具是一个theme ,将传递给该Provider的所有流。

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

主题上下文/ ThemeConsumer / ThemeConsumer.js

在此文件中,我们将与Consumer合作-这是一个“侦听,等待”上下文更改的组件。 该组件的子级是一个函数。 使用Consumer时这是必须的。

该函数接收当前上下文的值,并返回一个React Node ,换句话说,一个组件。

在文档中:参数的值(在我们的示例中为{theme => / *以根据上下文值* /}进行可视化显示)将等于此上下文的Provider树中最接近的父级的props theme

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

这里值得注意以下几点:
如果未明确选择主题,则需要自动选择组件主题,为此,我使用lodash - defaultTolodash 。 但是,可以通过许多其他方式来实现此功能。

就这样,主题上下文就可以使用了!

让我们看看如何应用它。 让我们创建一个简单的组件,该组件将侦听并响应应用程序的上下文。

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

因此,我们将<App />包装在提供程序中,现在该主题已可供我们应用程序中的所有组件消费者使用。 接下来, <App />返回<MyComponent /> ,这是 ,它将创建我们的组件并将其传递给我们应用程序的主题。 并且已经有一个主题作为参数:

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

我们可以在创建组件时使用它
  const renderMyComponent = theme => { //      }; 

工作代码可以在这里找到

就这样,我希望您对这篇文章有用。 在下一篇文章中,我将尝试创建一个媒体上下文 ,其功能将帮助我们可视化用户设备设备上的组件。

谢谢啦

Source: https://habr.com/ru/post/zh-CN462963/


All Articles