乐趣区

从React-15到React-16

  就像人们对移动应用程序和操作系统的更新感到兴奋一样,开发人员也应该对使用的框架更新感到兴奋。
各个框架的新版本给我们带来开箱即用的新功能和技巧。

  以下是将现有应用从 React 15 迁移到 React 16 时应考虑的一些优秀功能。

我们是时候对 React15 说再见了 ????

错误处理

React 16 引入了错误边界的新概念。

错误边界是捕获子组件树中任意位置 javascript 错误的 react 组件。他们记录这些错误,并且渲染备用的 UI,而不是崩溃的组件树。错误边界可以在渲染期间,生命周期方法,以及它们下面的整个树的构造函数中捕获错误。

如果一个类组件定义一个名为 componentDidCatch(error, info) 的新生命周期方法,那么它将变成错误边界:

class ErrorBoundary extends React.Component {constructor(props) {super(props);
    this.state = {hasError: false};
  }

  componentDidCatch(error, info) {
    // Display fallback UI
    this.setState({hasError: true});
    // You can also log the error to an error reporting service
    logErrorToMyService(error, info);
  }

  render() {if (this.state.hasError) {
      // You can render any custom fallback UI
      return <h1>Something went wrong.</h1>;
    }
    return this.props.children;
  }
}

接下来,你可以把它当做一个普通的组件来用。

<ErrorBoundary>  
   <MyWidget />
</ErrorBoundary>

componentDidCatch()方法的工作类似于 JavaScript catch {} 块,但对于组件。只有类组件可以是错误边界。实际上,大多数情况下,您只需要声明一次错误边界组件。然后你就可以在整个应用程序中使用它。

需要注意的是,错误边界只捕获其下面组件的错误。错误边界不能够捕获自身的错误,如果错误边界尝试渲染错误信息失败,那么错误将传播到其上方最近的错误边界,这一点,也类似于 catch{} 块在 javaScript 中的工作方式。

查看一个演示:
https://codepen.io/gaearon/pe…
有关错误处理的更多信息,可访问 error-handling-in-react-16

新的渲染返回类型:fragments(片段) 和 strings(字符串)

摆脱渲染时将组件包裹在 div 中。
您现在可以在 component 的 render 方法返回一个元素数组。与其他数组一样,您需要为每个元素添加一个 key 以避免报 key 警告:

render() {
  // No need to wrap list items in an extra element!
  return [// Don't forget the keys :)
    <li key="A">First item</li>,
    <li key="B">Second item</li>,
    <li key="C">Third item</li>,
  ];
}

从 React 16.2.0 开始,fragments 支持 JSX 的特殊片段语法,不需要 key。

支持返回字符串:

render() {return 'Look ma, no spans!';}

Portals

Portals 提供了一种将子项渲染在父组件的 DOM 层次结构之外的 DOM 节点中的好方法。

ReactDOM.createPortal(child, container)

其中,第一个参数 child 是任何可渲染的 react 元素,例如元素,字符串,或者片段。第二个参数 container 是 dom 元素

怎样使用它

当我们从组件的 render 方法返回一个元素时,它作为最近父节点的子节点挂载到 DOM 中:

render() {
  // React mounts a new div and renders the children into it
  return (
    <div>
      {this.props.children}
    </div>
  );
}

有时, 将子节点插入 DOM 中的其他位置是很有用的:

render() {
  // React does *not* create a new div. It renders the children into `domNode`.
  // `domNode` is any valid DOM node, regardless of its location in the DOM.
  return ReactDOM.createPortal(
    this.props.children,
    domNode
  );
}

portals 的一个典型用例是当父组件具有 overflow:hidden 或 z -index 样式时,但是您需要子容器在视觉上“突破”其容器。例如,对话框,hover 悬停卡片和 tooltip。
https://codepen.io/gaearon/pe…

自定义 DOM 属性

React 15 用于忽略任何未知的 DOM 属性。因为 React 不识别它,会跳过它们。

// Your code:
<div mycustomattribute="something" />

使用 React 15 会渲染一个空 div:

// React 15 output:
<div />

在 react16 中,输出将会是下面这样子(自定义属性将会显示且不会被忽略)

// React 16 output:
<div mycustomattribute="something" />

通过设置 state 为 NULL 来避免重复渲染

使用 React16,您可以直接从 setState()阻止 state 更新和重新渲染。你只需要让你的函数返回 null。

const MAX_PIZZAS = 20;

function addAnotherPizza(state, props) {
  // Stop updates and re-renders if I've had enough pizzas.
  if (state.pizza === MAX_PIZZAS) {return null;}

  // If not, keep the pizzas coming! :D
  return {pizza: state.pizza + 1,}
}

this.setState(addAnotherPizza);

访问 Refs

将 ref 传递给 render 中的元素时,可以在 ref 的当前属性中访问对该节点的引用。

const node = this.myRef.current;

ref 的值根据节点的类型而有所不同

  • 当在 HTML 元素上使用 ref 属性时,在构造函数中使用 React.createRef()创建的 ref 将接收底层 DOM 元素作为 current 属性。
  • 当 ref 属性用于自定义组件时,ref 对象接收组件的挂载实例作为 current。
  • 您不能函数组件上使用 ref 属性,因为它们没有实例。

关于 refs,更多

Context

Context 提供了一种通过组件树传递数据的方法,而无需逐级通过 props 传递。

React.createContext

const {Provider, Consumer} = React.createContext(defaultValue);

创建 {Provider,Consumer}。当 React 渲染上下文 Consumer 时,它将从树中它上面最接近的匹配 Provider 读取当前上下文值。
defaultValue 参数仅在 Consumer 在树中没有匹配的 Provider 时使用。这可以让我们不包装它们就能单独测试组件。注意:将 undefined 作为 Provider 值传递不会导致 Consumer 使用 defaultValue。

Provider

<Provider value={/* some value */}>

一个 React 组件,允许消费者订阅上下文更改。接受一个 value prop,传递给作为此 Provider 的后代的消费者。一个 Provider 可以连接到许多消费者,可以嵌套覆盖树中更深层的值。

Consumer

<Consumer>
  {value => /* render something based on the context value */}
</Consumer>

一个订阅上下文更改的 React 组件。

需要一个函数作为子元素。该函数接收当前上下文值并返回 React 节点。传递给函数的 value 参数将等于树中上述此上下文的最近 Provider 的 value prop。如果上面没有此上下文的 Provider,则 value 参数将等于传递给 createContext()的 defaultValue。

React 生命周期钩子

这些是使用 React16 时一定要尝试的一些功能!

退出移动版