React v16.6.0:lazy,memo 以及 contextType

October 23, 2018 by Sebastian Markbåge

今天我们发布了 React 16.6 版本,其中包含一些便利的新功能。例如为函数组件提供了类似于 PureComponent/shouldComponentUpdate 的方式,还有使用 Suspense 进行拆分代码以及在 class 组件中更简单使用 context 的方式。

更多详情可以查阅下面的更新日志

React.memo

过去,我们使用 PureComponent 或是 shouldComponentUpdate 来解决 class 组件在 props 不变时会重新渲染的问题。如今,你可以通过用 React.memo 包裹函数组件使其获得同样的能力。

const MyComponent = React.memo(function MyComponent(props) {
  /* 仅在 props 发生改变时才会 rerenders */
});

React.lazy: 依赖 Suspense 进行代码分割

您可能已经阅读过了 Dan 在冰岛的 JSConf 上关于 React Suspense 的演讲。现在,您可以通过 React.lazy() 包装动态加载的组件的方式使用 Suspense 来进行 代码分割 了。

import React, {lazy, Suspense} from 'react';
const OtherComponent = lazy(() => import('./OtherComponent'));

function MyComponent() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <OtherComponent />
    </Suspense>
  );
}

今后,Suspense 组件还会允许库作者们开发具备 Suspense 支持的数据获取功能。

注意:这项功能尚不可用于服务器端渲染,将在稍后的版本中支持。

static contextType

React 16.3 中我们引入了官方发布的 Context API 来替代过去的 Legacy Context

const MyContext = React.createContext();

我们收到了一些关于难以在 class 组件中使用 context 的反馈,因此我们添加了便捷的 API 以便于在 class 组件中使用 context 的值.

class MyClass extends React.Component {
  static contextType = MyContext;
  componentDidMount() {
    let value = this.context;
    /* 在首次挂载后使用 MyContext 执行副作用*/
  }
  componentDidUpdate() {
    let value = this.context;
    /* ... */
  }
  componentWillUnmount() {
    let value = this.context;
    /* ... */
  }
  render() {
    let value = this.context;
    /* 基于 MyContext 的值 render 某些内容*/
  }
}

static getDerivedStateFromError()

React 16 引入了错误边界来捕获在 React 的 render 中抛出的异常。我们已经拥有了在错误发生后被调用的生命周期方法 componentDidCatch。您可以通过它将错误记录到服务器,这非常有用。同时您还可以通过调用 setState 来展示对用户更友好的界面。

componentDidCatch 被触发之前,我们 render null 来替代抛出异常树。但这有时会破坏不期望该组件的 ref 为空的父组件。同时这个方法也无法帮助我们恢复服务端发生的异常, 因为 Did 这个生命周期方法不会在服务端渲染时被触发。

我们正在添加另一个错误捕获的方法,允许您在 render 完成之前回退 UI。请参阅文档 getDerivedStateFromError().

注意: getDerivedStateFromError() 尚不可用于服务端渲染。它被设计为在将来的版本中支持服务端渲染。我们提前发布,只是为了让您可以开始准备如何使用它。

在 StrictMode 中被弃用的

16.3 中我们介绍了 StrictMode 组件。它允许您选择对可能在将来导致问题的模式进行提前预警。

我们在 StrictMode 的弃用 API 列表中再次添加了两个 API。如果您不使用StrictMode 则无需担忧;这些警告不会影响到您。

  • ReactDOM.findDOMNode() - 这个 API 经常被误解与滥用。它在 React 16 中可能会出乎意料地慢。请查阅文档以获得可能的升级方式。
  • Legacy Context 使用 contextTypes 以及 getChildContext 的 Legacy context 使 React 变得比它所需要更大更慢。 这就是为什么我们强烈期望您升级到 新的 context API。希望添加 contextType API 能够改善这一切。

如果您在升级时遇到问题,我们希望听到您的反馈意见。

安装

npm 的源中提供了 React v16.6.0。

要使用 Yarn 安装 React 16,请运行:

yarn add react@^16.6.0 react-dom@^16.6.0

要使用 npm 安装 React 16,请运行:

npm install --save react@^16.6.0 react-dom@^16.6.0

我们还通过 CDN 提供了 React 的 UMD 版本:

<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>

更详细 安装说明,请参阅文档。

更新日志

React

  • 添加 React.memo() 作为 PureComponent 在函数组件中的替代品。 (@acdlite#13748)
  • 添加 React.lazy() 以支持代码拆分组件。 (@acdlite#13885)
  • React.StrictMode 现在会警告使用旧的 context API。 (@bvaughn#13760)
  • React.StrictMode 现在会警告使用 findDOMNode。 (@sebmarkbage#13841)
  • 重命名 unstable_AsyncModeunstable_ConcurrentMode。 (@trueadm#13732)
  • 重命名 unstable_PlaceholderSuspensedelayMsmaxDuration。 (@gaearon#13799@sebmarkbage#13922)

React DOM

  • contextType 添加了在 class 组件中更人性化的订阅方式。 (@bvaughn#13728)
  • 添加 getDerivedStateFromError 生命周期方法以在将来的异步服务器端渲染中捕获错误。 (@bvaughn#13746)
  • 当使用 <Context> 而不是 <Context.Consumer> 时,给予警告。 (@trueadm#13829)
  • 修复iOS Safari上的灰色覆盖层。 (@philipp-spiess#13778)
  • 修复在开发中覆盖了 window.event 的错误。 (@sergei-startsev#13697)

React DOM Server

Scheduler (实验阶段)