原文地址:React's ⚛️ new Context APIjavascript
做者:kentcdoddshtml
这再也不是一个 实验性的 API
,而且它更符合 工程化
的理念,目前它已成为 React 一级棒的 API
。前端
⚠️ :你们能够经过 newsletter 获取我最新的资讯,我通常每两周经过邮件发送一次,你们能够经过本身的收件箱获取更多的内容。java
React
中的 context API
相信你们都知道吧,可能跟大伙同样,当看到 React
的官方文档是这样时,都不敢直接使用它。react
第一条搜索结果显示的就是 为何不建议使用 context,让你们瞬间产生忧虑,该章节是这么描述 context
的:git
若是你想让你的应用更加稳定,就别使用
context
,由于这是一个实验性的API
,在将来的React
版本中可能会发生改变。github
⚠️ 注意,这里的改变包括 中断
,终止
,再也不使用
的含义。redux
你曾经历过尝试在一个 层级很深的组件
中获取 最外层组件
的 state
的痛苦么,这种痛苦叫 prop drilling
,可谓让人接近崩溃的。当遇到这种情形时,你确定不会喜欢用 props
来传递数据,由于若是中间有个组件发生改变,这个代价将是几何 :joy:。api
实际上,你能够经过使用常规的 JavaScript module
来规避以上的问题,将数据存放在某个 module
中,就能够实如今任何地方 访问/导入
,但这么作想要 更新
却很麻烦(你必须实现一个 event
在数据更新时触发,通知用户数据发生改变),而且,服务端渲染
对 module
也会有 影响。微信
所以,像 redux 这样的负责 状态管理
的第三方库进入了你们的视野。它容许你在任何地方从 store
获取数据,你须要作的只是使用 <Provider />
包装一下,而后就能够神奇地在 connected
的组件中轻松地获取想要的数据了。
然而,若是我告诉你 <Provider />
就是在使用 context
这个 实验性 API
呢?😱 事实上也是这样的!provider
组件将数据存进 context
中,connect
高阶组件从 context
获取数据,因此,redux
并不容许你的数据能够在任何地方访问,context
就是这样。
因此,为何还要使用 context
呢?多是你们已经深深地爱上它了吧!即便你没有直接使用 context
,你的应用程序也会经过引用像 react-redux, MobX-react, react-router, glamorous 这样的第三方库间接用到它。
如今清楚了,咱们是如此地热爱 context
,但官方文档的警告依然还在:在 React 的将来版本中,可能再也不使用它
,好消息是,context
要正式跟你们打招呼了,你们极有可能比以前更爱它。
一个月前,React 团队
从 yarn,rust 和 Ember 的 rfcs 仓库
受到启发,创建了一个本身的 rfcs 仓库。仓库第一个 PR
来自 Andrew Clark(React 团队核心成员),PR
标题为 New version of context,其中 Andrew Clark
概述了将来新版本的 context
是怎样的,以后还存在一些有趣的讨论,几天后,Andrew Clark
就向 React
仓库提了一个 New context API 的 PR
。
那么,到底有什么改变呢?肉眼估计新的 API
与以前的 API
存在百万级别的差别。这是我作的一个简单的 示例
const ThemeContext = React.createContext('light')
class ThemeProvider extends React.Component {
state = {theme: 'light'}
render() {
return ThemeContext.provide(this.state.theme, this.props.children)
}
}
const ThemeConsumer = ({children}) => ThemeContext.consume(children)
class App extends React.Component {
render() {
<ThemeProvider>
<ThemeConsumer>{val => <div>{val}</div>}</ThemeConsumer>
</ThemeProvider>
}
}
复制代码
你可能注意到示例中使用到一个
render prop
,但实际上并无任何关于须要使用render prop
的context API
,你可使用context API
轻松实现高阶组件
或其余功能。
新的 context API
主要由如下三部分组成
React.createContext
用于传递 初始值
(可选择 使用 bitmask 的一个奇妙的选择性退出函数),返回一个包含 provider
和 consumer
的对象provide
函数使用 higher
,并能够接收任何值consume
函数在 provider
以后任何地方使用,并传递一个返回 JSX
的函数(这有点像 render prop
组件,但 consume
不是组件)。我对这个 API
充满了期待,React 团队
也将会移除 context 是实验性 API
的警告,由于它如今是框架 一级棒的特性。这也意味着你们将再也不那么担忧使用 context
来解决应用中 prop-drilling
的问题了,对 Redux
也将再也不那么依赖,对 React
将更加喜欢。
我最近看到的,大概意思是:
你们不是很愿意保持使用提倡的
render
方法,加剧了prop drilling
问题,因此,最终想经过redux
来缓解
因此,我认为若是咱们不过早或武断地去破坏 render
方法,咱们可能就不会那么痛苦,即使最终咱们实在没有办法避免,咱们也能够经过核心的 React API
来解决。
我看到了一个关于 context API
(或普通的 render prop pattern
)的问题不少次,就是如何组合 providers
和 consumers
,当在一个 render
方法中把一堆 render prop
组件放在一块儿时,就会像这样 嵌套
那么,咱们能够作点什么来避免呢?其实,我的以为没有那么糟糕,若是你以为这样并很差,那么可使用常规的方法来解决它:utility
函数/组件,下面是一个示例:
const ThemeContext = React.createContext('light')
class ThemeProvider extends React.Component {/* code */}
const ThemeConsumer = ({children}) => ThemeContext.consume(children)
const LanguageContext = React.createContext('en')
class LanguageProvider extends React.Component {/* code */}
const LanguageConsumer = ({children}) => LanguageContext.consume(children)
function AppProviders({children}) {
return (
<LanguageProvider>
<ThemeProvider>
{children}
</ThemeProvider>
</LanguageProvider>
)
}
function ThemeAndLanguageConsumer({children}) {
return (
<LanguageConsumer>
{language => (
<ThemeConsumer>
{theme => children({language, theme})}
</ThemeConsumer>
)}
</LanguageConsumer>
)
}
class App extends React.Component {
render() {
<AppProviders>
<ThemeAndLanguageConsumer>
{({theme, language}) => <div>{theme} and {language}</div>}
</ThemeAndLanguageConsumer>
</AppProviders>
}
}
复制代码
这里的目标是使用常见的案例,结合特殊功能的函数/组件,使案例更加 工程化
。
除此以外,你们还能够参考 jmeas 的 react-composer。
但须要说起的是,在实践中,我并不建议你们嵌套渲染 props components
,不管何时,均可以选择建立多个简单易用的组件,而后组合使用。
正如上面所说的,我对这个 API
充满了期待。目前暂未发布,但应该会包含在下一个 minor
版本中。不一样担忧,以前的 API
会继续正常工做,直到下一个 major
版本发布,因此,每一个人都有时间迁移。还有不要忘了,React
团队在 Facebook
有超过 50,000
个 React components
须要维护,因此,未来颇有可能会发布一个 codemod
去自动更新大多数人的代码(就像以往同样)。
我很高兴这个 新 API
可以提供,正如我在 twitter 中说起的。
关注微信公众号:创宇前端(KnownsecFED),码上获取更多优质干货!