前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >45. 精读《React's new Context API》

45. 精读《React's new Context API》

作者头像
黄子毅
发布2022-03-14 16:04:10
4730
发布2022-03-14 16:04:10
举报
文章被收录于专栏:前端精读评论

本周精读的文章是 React's new Context API。

1 引言

React 即将推出全新的 Context api,让我们一起看看。

2 概述

像 react-redux、mobx-react、react-router 都使用了旧 Context api,可谓 context 无处不在。

新版 Context 语法是这样的:

代码语言:javascript
复制
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>
  }
}
  • React.createContext 创建新的 Context 并赋初始值。返回的对象包含 providerconsumer
  • provide 是一个容器,它所有的子元素都能通过 consumer 访问到这个 Context 的值。

其实这种思想在 react-broadcast 已经被实现,现在变成了官方 API。

当然如果多个 Context 同时存在,可能会出现 jsx 的嵌套地狱,不过这个情况可以通过拆分模块,或者以如下方式定义多重 Consumer 来解决:

代码语言:javascript
复制
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>
  }
}

3 精读

最大的问题是,React17 会废除旧 Context 这个 api,许许多多的库需要升级,不过到时候也应该会出现 codemod 自动更新吧。

从 15.0 升级到 16.0 时因为项目中大量使用 React.PropTypes 的地方需要重构,从 16.0 升级到 17.0 时,就不是项目要升级了,而是比如 react-redux 这类库要偷偷升级 context 的用法,可见 React 大版本间生态完全兼容是不可能了。

Context 多层嵌套问题

一种方式是通过构造原文中描述的 ThemeAndLanguageConsumer 聚合 Consumer 解决,也可以使用比如 react-context-composer 这种库优雅的解决。摘自 如何解读 react 16.3 引入的新 context api@淡苍

绕过 shouldComponentUpdate

像 redux、mobx - react 这些库,都使用了 forceUpdate 绕过 shouldComponentUpdate 机制。原因是这些全局状态管理工具接管了自己的组件更新时机,纵使保留组件原本的更新机制,但当数据流发生变化时,需要绕过一切阻碍,直接触发目标组件的一整套渲染生命周期。

好在新的 Context api 也拥有如此特性,可以在 context 改变时,直接更新即使 shouldComponentUpdate: false 的组件。

是否还需要 redux

正如很多人说的,这要看我们是怎么使用 redux 了。

在之前一篇精读 前端数据流哲学 中,我提到了 redux、mobx、rxjs 这三大流派的竞争力。

其中 redux 其实是最没有竞争力的数据流框架,我们暂且抛开函数式和优雅性不说,从功能上说,看看 redux 到底做了啥?利用 react 特性,利用全局数据流解决组件间数据通信问题。抛开 react-redux,只看 redux,剩下不能再简单的 Action 与 Reducer。

再看 mobx,稍微好一点,其主打能力是自动追踪变量引用,当变量被修改时自动刷新视图,可见它的竞争力不仅仅在组件数据的打通,自动绑定带来的效率提升是一大亮点。

最后是 rxjs,其主打能力压根不在 react,核心竞争力在数据处理能力,与数据源的抽象,做到了副作用隔离在数据处理流程之外。

可见技术框架也是如此,核心竞争力在哪,未来就在哪。

是否 flux 多 store 思想再度崛起?

我觉得几乎不可能。

新的 Context API 给了开发者创造多个 context 的能力,可不是在项目中创建多个 store,制造混乱的呀。我们之前说过,除了数据流框架,像 react-router,或者一些国际化组件也会使用到 context 传递数据,本质上是需要 context 解决对数据透传的控制能力。

举个例子,国际化参数可以让组件一层一层透传,但调用到 node_modules 组件时,我们无法修改其 dom 结构,怎么让这个参数强制透传呢?所以必须使用 context 对所有需要国际化的组件注入 props,而这个注入变量由顶层 Provider 控制。比如 antd local-provider。

然而共享一个 context 可能会冲突啊,现在你创建你的,我创建我的,咱们都互不影响,未来数据流框架大家会用的更爽,甚至一个项目可以同时并存多套数据流框架,因为互不影响嘛。

4 总结

然而新的 Context api 并不是银弹,无法解决所有问题,更不能解决业务组件与项目数据流绑定,导致的耦合问题。

因为不论怎么组织数据流,官方提供了怎样的 api,只要我们想给组件注入数据,那么注入的那个节点就一定依赖一个特性的项目环境,或者变量,比如某个 consumer

数据流框架也无法被取代,因为数据流框架的核心竞争力不在数据的依赖注入上,而是对数据的处理。

当然这次变化带来最乐观的改变是,react 拥有了一个稳定好用的依赖注入官方 api,在处理国际化这种需要拿 Context 小用一下的场景,可以不依赖第三方库了!代码如下:

代码语言:javascript
复制
const Locale = React.createContext({
  text: 'menu'
})

class MyComponent extends React.Component {
  render() {
    <Locale.consume>
      {text => (
        <span>This is the {text}</span>
      )}
    </Locale.consume>
  }
}

class App extends React.Component {
  render() {
    <Locale.provide>
      <MyComponent />
    </Locale.provide>
  }
}

5 更多讨论

讨论地址是:精读《React's new Context API》 · Issue #64 · dt-fe/weekly

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-06-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端精读评论 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 引言
  • 2 概述
  • 3 精读
    • Context 多层嵌套问题
      • 绕过 shouldComponentUpdate
        • 是否还需要 redux
          • 是否 flux 多 store 思想再度崛起?
          • 4 总结
          • 5 更多讨论
          相关产品与服务
          容器服务
          腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档