使用 React 16.3,我们现在可以访问全新的上下文 API。 使用 React 的旧上下文 API,官方建议开发人员避免使用它,但现在新的上下文 API 是一等公民。
虽然不是作为 Redux 或 MobX 等状态管理库的替代品,但上下文 API 允许在多个组件之间共享全局数据,而无需将其作为 props 传递。 它解决了一个常见的问题,称为 prop-drilling 问题,其中 props 需要向下传递到树中的多个组件才能到达需要它的组件。
新 API 对于提供树中大部分组件所需的数据特别有用。 像选定主题或选定区域选项这样的全局首选项就是两个很好的例子。
在这篇文章中,我们将用尽可能少的语言解释如何使用新的上下文 API。 我们将创建一个简单的 Locale 上下文,为应用程序中的组件提供英语和法语之间的语言偏好。 请注意,它只是作为一个简单的示例来展示应用程序的全局偏好,对于 React 中的真正 i18n,像 i18next 这样的更强大的解决方案更合适。
React.createContext
要创建新上下文,请使用 React 的新 createContext 函数:
export const LocaleContext = React.createContext('en');
在这里,我们还将 'en' 的默认值传递给上下文,但如果您愿意,也可以省略此默认值。
createContext
函数返回一个 Provider 和一个 Consumer 组件。
提供者
Provider 组件用于将组件包装在需要从上下文访问值的树中。 在这里,让我们创建一个 LocaleProvider 组件,它包装了我们的 LocaleContext 的提供程序,并提供了一种更改上下文的 locale 值的方法:
上下文/LocaleContext.js
import React from 'react'; export const LocaleContext = React.createContext(); class LocaleProvider extends React.Component { constructor(props) { super(props); this.changeLocale = () => { this.setState(state => { const newLocale = state.locale === 'en' ? 'fr' : 'en'; return { locale: newLocale }; }); }; this.state = { locale: 'en', changeLocale: this.changeLocale }; } render() { return ( <LocaleContext.Provider value={this.state}> {this.props.children} </LocaleContext.Provider> ); } } export default LocaleProvider;
请注意 LocaleProvider 组件如何只是我们上下文的 Provider 组件的薄包装器。 上下文的值使用 value 属性传递给提供者,然后我们只渲染 LocaleContext 的子项。
我们将组件的状态作为上下文值传递,从那里传递语言环境值和更改值的 changeLocale
方法将可用。
使用提供者
我们可以在 App 组件的顶层使用我们的提供程序:
应用程序.js
import React, { Component } from 'react'; import LocaleProvider from './context/LocaleContext'; import Greeting from './Greeting'; import ToggleLocale from './ToggleLocale'; class App extends Component { render() { return ( <LocaleProvider> <Greeting /> <ToggleLocale /> </LocaleProvider> ); } } export default App;
消费者
现在剩下要做的就是使用 Consumer 组件从上下文中访问值。
我们的 Greeting 组件如下所示:
问候.js
import React from 'react'; import { LocaleContext } from './context/LocaleContext'; export default () => { return ( <LocaleContext.Consumer> {localeVal => localeVal.locale === 'en' ? <h1>Welcome!</h1> : <h1>Bienvenue!</h1> } </LocaleContext.Consumer> ); };
我们的 ToggleLocale 组件看起来像这样:
ToggleLocale.js
import React from 'react'; import { LocaleContext } from './context/LocaleContext'; export default () => { return ( <LocaleContext.Consumer> {localeVal => ( <button onClick={localeVal.changeLocale}>Change language</button> )} </LocaleContext.Consumer> ); };
Consumer 组件使用渲染道具模式并期望一个函数作为其子道具,该函数将从上下文中接收值。 然后我们可以访问上下文的值并调用它提供的方法。
有了这个,我们可以在 Welcome 和 Bienvenue 之间切换应用程序的问候消息。
在我们的示例中,Greeting 和 ToggleLocale 组件是 LocaleProvider 组件的直接子组件,但它们可以位于组件树的任何深度并且它们仍然会只要使用上下文的消费者组件并且提供者位于树的更高位置,就可以访问全局上下文数据。
⚛️ 有了这个,你应该很好地开始在你的应用程序中使用新的上下文 API。 更多信息也可以参考【X48X】官方文档【X65X】。