React v16.13.0

February 26, 2020 by Sunil Pai

今天我们发布了 React 16.13.0。此版本修复了部分 bug 并添加了新的弃用警告,以助力接下来的主要版本。

新的警告

Render 期间更新的警告

React 组件不应在 render 期间对其他组件产生副作用。

在 render 期间调用 setState 是被支持的,但是 仅仅适用于同一个组件。 如果你在另一个组件 render 期间调用 setState,现在你将会看到一条警告。

Warning: Cannot update a component from inside the function body of a different component.

这些警告将会帮助你找到应用中由意外的状态改变引起的 bug。 在极少数情况下,由于渲染,你有意要更改另一个组件的状态,你可以将 setState 调用包装为 useEffect

冲突的样式规则警告

当动态地应用包含了全写和简写的 style 版本的 CSS 属性时,特定的更新组合可能会导致样式不一致。例如:

<div style={toggle ? 
  { background: 'blue', backgroundColor: 'red' } : 
  { backgroundColor: 'red' }
}>
  ...
</div> 

你可能期待这个 <div> 总是拥有红色背景,不论 toggle 的值是什么。然而,在 truefalse之间交替使用toggle时,背景色开始是 red,然后在 transparentblue之间交替, 正如你能在这个 demo 中看到的

React 现在检测到冲突的样式规则并打印出警告。要解决此问题,请不要在 style 属性中混合使用同一CSS属性的简写和全写版本。

某些废弃字符串 ref 的警告

字符串 ref 是过时的 API 这是不可取的,将来将被弃用:

<Button ref="myRef" />

(不要将字符串 ref 与一般的 ref 混淆,后者仍然完全受支持。)

在将来,我们将提供一个自动脚本(“codemod”),以从字符串 ref 中迁移。然而,一些罕见的案例不能自动迁移。此版本在弃用之前添加了一个新的警告仅适用于那些情况

例如,如果将字符串 ref 与 Render Prop 模式一起使用,则它将触发:

class ClassWithRenderProp extends React.Component {
  componentDidMount() {
    doSomething(this.refs.myRef);
  }
  render() {
    return this.props.children();
  }
}

class ClassParent extends React.Component {
  render() {
    return (
      <ClassWithRenderProp>
        {() => <Button ref="myRef" />}
      </ClassWithRenderProp>
    );
  }
}

这样的代码通常暗含 bug。(你可能希望 ref 在 ClassParent 上可用,但是它被放在 ClassWithRenderProp 上)。

你很可能没有这样的代码。如果是有意为之,请将其转换为 React.createRef()

class ClassWithRenderProp extends React.Component {
  myRef = React.createRef();
  componentDidMount() {
    doSomething(this.myRef.current);
  }
  render() {
    return this.props.children(this.myRef);
  }
}

class ClassParent extends React.Component {
  render() {
    return (
      <ClassWithRenderProp>
        {myRef => <Button ref={myRef} />}
      </ClassWithRenderProp>
    );
  }
}

Note

要查看此警告,你需要在你的 Babel plugins 中安装 babel-plugin-transform-react-jsx-self。它必须 仅仅 在开发模式下启用。

如果你使用 Create React App 或者用 babel 7+ 的 React preset,那么默认情况下已经安装了这个插件。

弃用 React.createFactory

React.createFactory为 React 创建一个帮助器元素。此版本向该方法添加了一个弃用警告。它将在未来的主要版本中删除。

React.createFactory 替换为普通的 JSX 。或者可以复制并粘贴此单行辅助对象或将其发布为库:

let createFactory = type => React.createElement.bind(null, type);

它的作用完全相同。

弃用 ReactDOM.unstable_createPortal 推荐 ReactDOM.createPortal

当 React 16 发布时,createPortal 成为一个官方支持的 API。

但是,我们保留了 unstable_createPortal 作为受支持的别名,以使采用它的少数库正常工作。我们现在反对使用 unstable 别名。直接使用 createPortal 而不是 unstable_createPortal。它有完全相同的签名。

其他改进

Hydration 过程中组件堆栈的警告

React 将组件堆栈添加到其开发警告中,使开发人员能够隔离 bug 并调试他们的程序。此版本将组件堆栈添加到许多以前没有的开发警告中。举个例子,考虑一下以前版本中的 hydration 警告:

控制台警告的屏幕截图,简单地说明 hydration 不匹配的性质:

虽然它指出了代码中的一个错误,但不清楚错误在哪里存在,以及下一步该怎么做。此版本向此警告添加了一个组件堆栈,使其看起来如下所示:

控制台警告的屏幕截图,说明 hydration 不匹配的性质,但也包括组件堆栈:

这样可以清楚地看出问题所在,并让你更快地找到并修复错误。

值得注意的错误修复

此版本包含其他一些值得注意的改进:

  • 在严格的开发模式下,React 调用生命周期方法两次,以清除任何可能不需要的副作用。此版本将此行为添加到 shouldComponentUpdate 中。这不会影响大多数代码,除非在 shouldComponentUpdate 中有副作用。要解决此问题,请将具有副作用的代码移到 componentDidUpdate 中。
  • 在严格开发模式下,使用遗留上下文 API 的警告不包括触发警告的组件堆栈。此版本将丢失的堆栈添加到警告中。
  • onMouseEnter 现在在被禁用的 <button> 对象上不能被触发。
  • 自从我们发布 v16 以来,ReactDOM 缺少一个 version 导出。这个版本又添加了它。我们不建议在应用程序逻辑中使用它,但是在调试同一页面上的 ReactDOM 的不匹配/多个版本时,它非常有用。

我们感谢所有帮助揭示和解决这些和其他问题的贡献者。你可以找到完整的变更日志 如下

安装

React

React v16.13.0 现在在 npm 库中已经可用。

用 Yarn 安装 React 16,运行:

yarn add react@^16.13.0 react-dom@^16.13.0

用 npm 安装 React 16,运行:

npm install --save react@^16.13.0 react-dom@^16.13.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

  • 当字符串 ref 的使用方式不符合将来的代码模式时发出警告 (@lunaruan in #17864)
  • 弃用 React.createFactory() (@trueadm in #17878)

React DOM

并发模式(实验)

Is this page useful?编辑此页面