React v16.4.0: Pointer Events

May 22, 2018 by Andrew Clark

最新的版本(16.4.0)增加了对经常请求的特性——指针事件的支持;

这个版本也包含了对于 getDerivedStateFromProps 的bug修复工作。

It also includes a bugfix for getDerivedStateFromProps. 查看下面完整的更新日志

指针事件

在 React DOM 中,现在可以使用如下指针事件:

  • onPointerDown
  • onPointerMove
  • onPointerUp
  • onPointerCancel
  • onGotPointerCapture
  • onLostPointerCapture
  • onPointerEnter
  • onPointerLeave
  • onPointerOver
  • onPointerOut

请注意,这些事件只能在支持 指针事件 规范的浏览器中工作。(在编写本文时,包括Chrome、Firefox、Edge和Internet Explorer的最新版本。) 如果你的应用程序依赖于指针事件,我们建议使用第三方指针事件 polyfill 。为了避免增加包文件的大小,我们在 React DOM 中不包含这样的 polyfill。(译者注:Polyfill 是一块代码,用来为旧浏览器提供它没有原生支持的较新的功能。)

在沙箱中查看运行这个案例。

非常感谢 Philipp Spiess 对于这个改变的巨大贡献!

修复 getDerivedStateFromProps bug

不管更新的原因是什么,getDerivedStateFromProps 这个函数在组件的每一次渲染中都会被调用。以前,只有当父组件重新渲染时,才会调用这个函数。同时,当这个组件执行setState时不会触发这个函数。这是在最初实施时的疏忽造成的 bug,现在已经修复。这个函数之前的行为更类似于compoenentWillReceiveProps这个函数。但是,改进后的行为确保了与 React 框架即将推出的异步渲染模式的兼容。

这个 bug 修复不会影响大部分应用。但是可能会造成一小部分组件部分的问题。这些罕见的案例主要影响在两个大类:

1. 避免getDerivedStateFromProps函数的副作用

就像渲染的方法,getDerivedStateFromProps 函数应该是一个纯净的 props 和 state 的函数。这个函数的副作用在 getDerivedStateFromProps从来没有支持。但由于它现在比过去的任何时候更受欢迎,最近的变化可能暴露出之前未被发现的一些bug。

函数产生副作用的代码,应该移动到其他方法中。例如,流量分派方法,通常属于原始事件处理程序内;手动DOM变化方法,通常属于内部 componentDidMount 或 componentDidUpdate 生命周琼函数中。你可以在我们最近关于准备发布的异步呈现文章中,了解更多信息。

2. 计算受控属性时,将新 props 和上一个 props 进行比较

下面的代码假设 getDerivedStateFromProps 函数只在 props 更新的时候触发:

static getDerivedStateFromProps(props, state) {
  if (props.value !== state.controlledValue) {
    return {
      // Since this method fires on both props and state changes, local updates
      // to the controlled value will be ignored, because the props version
      // always overrides it. Oops!
      controlledValue: props.value,
    };
  }
  return null;
}

解决这个问题的可能的方法是:将传入值与前一个值进行比较。具体方法是将前面的 props存储在 state 中。

static getDerivedStateFromProps(props, state) {
  const prevProps = state.prevProps;
  // Compare the incoming prop to previous prop
  const controlledValue =
    prevProps.value !== props.value
      ? props.value
      : state.controlledValue;
  return {
    // Store the previous props in state
    prevProps: props,
    controlledValue,
  };
}

然而, 在 state 中存储“镜像” props 通常会包含 bug, 不管你使用新的 getDerivedStateFromProps 函数,或者旧的 componentWillReceiveProps 函数。我们发表了一篇后续的博客文章,更详细地解释了这些问题, 并且提出了不涉及getDerivedStateFromProps()函数的更简单的解决方案

安装

你可以通过 npm 获取 React 16.4.0 版本。

使用 Yarn 安装 React 16 版本,运行下面的代码:

yarn add react@^16.4.0 react-dom@^16.4.0

使用 npm 安装安装 React 16 版本,运行下面的代码:

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

我们也提供了通过 CDN 的 UMD 方式搭建一个 React:

<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 DOM

  • Add support for the Pointer Events specification. (@philipp-spiess in #12507)
  • Properly call getDerivedStateFromProps() regardless of the reason for re-rendering. (@acdlite in #12600 and #12802)
  • Fix a bug that prevented context propagation in some cases. (@gaearon in #12708)
  • Fix re-rendering of components using forwardRef() on a deeper setState(). (@gaearon in #12690)
  • Fix some attributes incorrectly getting removed from custom element nodes. (@airamrguez in #12702)
  • Fix context providers to not bail out on children if there’s a legacy context provider above. (@gaearon in #12586)
  • Add the ability to specify propTypes on a context provider component. (@nicolevy in #12658)
  • Fix a false positive warning when using react-lifecycles-compat in <StrictMode>. (@bvaughn in #12644)
  • Warn when the forwardRef() render function has propTypes or defaultProps. (@bvaughn in #12644)
  • Improve how forwardRef() and context consumers are displayed in the component stack. (@sophiebits in #12777)
  • Change internal event names. This can break third-party packages that rely on React internals in unsupported ways. (@philipp-spiess in #12629)

React Test Renderer

  • Fix the getDerivedStateFromProps() support to match the new React DOM behavior. (@koba04 in #12676)
  • Fix a testInstance.parent crash when the parent is a fragment or another special node. (@gaearon in #12813)
  • forwardRef() components are now discoverable by the test renderer traversal methods. (@gaearon in #12725)
  • Shallow renderer now ignores setState() updaters that return null or undefined. (@koba04 in #12756)

React ART

  • Fix reading context provided from the tree managed by React DOM. (@acdlite in #12779)

React Call Return (Experimental)

  • This experiment was deleted because it was affecting the bundle size and the API wasn’t good enough. It’s likely to come back in the future in some other form. (@gaearon in #12820)

React Reconciler (Experimental)