React v16.3.0: New lifecycles and context API

几天前,我们写了一篇关于行将到来的对我们的传统生命周期要领的变动的文章,包含逐渐迁徙战略。在React 16.3.0中,我们增加了一些新的生命周期要领来协助迁徙。我们还引入了新的API,用于长时间要求的特征:一个官方的上下文API、一个ref转发API和一个更语意化的ref API。

请继承浏览,相识更多关于这个版本的信息。

官方认证的 Context API

多年来,React为Context供应了一个实验性的API。虽然它是一个壮大的东西,然则由于API中固有的题目,它的运用是不受迎接的,因而我们盘算用一个更好的API来替换这实验性的API。

React 16.3引入了一个新的Context API,它更高效,同时支撑静态范例搜检和深度更新。

注重

旧的ContextAPI 将继承保留到React 16.x,所以您将有时间迁徙。

下面是一个示例,申明怎样运用新的上下文API注入“主题”:

## by 司徒正美
const ThemeContext = React.createContext('light');

class ThemeProvider extends React.Component {
  state = {theme: 'light'};

  render() {
    return (
      <ThemeContext.Provider value={this.state.theme}>
        {this.props.children}
      </ThemeContext.Provider>
    );
  }
}

class ThemedButton extends React.Component {
  render() {
    return (
      <ThemeContext.Consumer>
        {theme => <Button theme={theme} />}
      </ThemeContext.Consumer>
    );
  }
}

createRef API

之前,React供应了两种治理refs的要领:字符串ref API和回调ref API。只管字符串ref API比较轻易,然则它有几个瑕玷,所以我们的官方引荐是运用回调ref。

React 16.3为治理refs供应了一个新的计划,它为字符串ref供应了轻易,而且没有任何瑕玷:

## by 司徒正美

class MyComponent extends React.Component {
  constructor(props) {
    super(props);

    this.inputRef = React.createRef();
  }

  render() {
    return <input type="text" ref={this.inputRef} />;
  }

  componentDidMount() {
    this.inputRef.current.focus();
  }
}

注重

除了新的createRef API外,回调refs将继承获得支撑。

您不需要在组件中替换回调refs。它们轻微天真一些,因而它们将继承作为一个高等特征。

forwardRef API

高阶组件(或HOCs)是在组件之间重用代码的经常使用要领。基于上面的主题上下文示例,我们能够会建立一个暂时对象,将当前的“主题”作为一个属性注入:

## by 司徒正美

function withTheme(Component) {
  return function ThemedComponent(props) {
    return (
      <ThemeContext.Consumer>
        {theme => <Component {...props} theme={theme} />}
      </ThemeContext.Consumer>
    );
  };
}

我们能够运用上述特别的体式格局将组件连接到主题上下文,而没必要直接运用主题上下文。比方:

## by 司徒正美

class FancyButton extends React.Component {
  buttonRef = React.createRef();

  focus() {
    this.buttonRef.current.focus();
  }

  render() {
    const {label, theme, ...rest} = this.props;
    return (
      <button
        {...rest}
        className={`${theme}-button`}
        ref={this.buttonRef}>

        {label}
      </button>
    );
  }
}

const FancyThemedButton = withTheme(FancyButton);

// We can render FancyThemedButton as if it were a FancyButton
// It will automatically receive the current "theme",
// And the HOC will pass through our other props.
<FancyThemedButton
  label="Click me!"
  onClick={handleClick}
/>;

HOCs一般会将props通报给它们包装的组件。不幸的是,refs没有冲透进去。这意味着假如我们运用FancyThemedButton,我们就不能将ref增加到FancyButton中,因而我们没法挪用focus()。

新的代办API经由过程供应一种要领来阻拦一个ref,并将其转发为一个一般的props,从而处理了这个题目:

## by 司徒正美

function withTheme(Component) {
  // Note the second param "ref" provided by React.forwardRef.
  // We can attach this to Component directly.
  function ThemedComponent(props, ref) {
    return (
      <ThemeContext.Consumer>
        {theme => (
          <Component {...props} ref={ref} theme={theme} />
        )}
      </ThemeContext.Consumer>
    );
  }

  // These next lines are not necessary,
  // But they do give the component a better display name in DevTools,
  // e.g. "ForwardRef(withTheme(MyComponent))"
  const name = Component.displayName || Component.name;
  ThemedComponent.displayName = `withTheme(${name})`;

  // Tell React to pass the "ref" to ThemedComponent.
  return React.forwardRef(ThemedComponent);
}

const fancyButtonRef = React.createRef();

// fancyButtonRef will now point to FancyButton
<FancyThemedButton
  label="Click me!"
  onClick={handleClick}
  ref={fancyButtonRef}
/>;

组件生命周期钩子的变化

React的类组件API已存在多年,几乎没有变化。然则,当我们为更高等的特征(比方毛病边境和行将到来的异步衬着形式)增加支撑时,我们以它原本没有盘算的体式格局来扩大这个模子。

比方,在当前的API中,用一些非平常的手腕来阻挠初始衬着是很轻易的。在某种程度上,这是由于有太多的钩子来完成这项既定的使命,而且还不清晰哪一个是最好的。我们已注重到毛病处理的中缀行动一般不会被斟酌,而且能够致使内存走漏(这也会影响行将到来的异步衬着形式)。当前的类组件API也使其他的事变变得复杂,比方我们的代码优化器(Prepack)的事变。

componentWillMount, componentWillReceiveProps, componentWillUpdate这些钩子很轻易激发题目,而且也严峻骚动扰攘侵犯React的生命周期。基于这些缘由,我们将烧毁这些要领,以支撑更好的替换计划。

我们认识到这一变化将影响很多现有的组件。因而,迁徙途径将尽能够平缓,并供应迁徙计划。(在Facebook,我们具有5万多个React组件。我们也依赖于一个渐进的宣布周期!

注重

弃用正告将在React16今后的版本中启用, 一向保留到17宣布时。

纵然在React17中,依然能够运用它们,然则它们将增加“UNSAFE_”前缀,以表明它们能够致使题目。我们还预备了一个自动化的剧本,以便现有代码中重命名它们。

除了烧毁不安全的生命周期钩子外,我们还增加了一些新的生命周期钩子:

getDerivedStateFromProps 用来componentWillReceiveProps。

getSnapshotBeforeUpdate,用在更新前从DOM中安全地读取属性。

StrictMode 组件

<StrictMode />是一种特地用于暴露潜伏题目的东西。与<Fragment />一样,<StrictMode/>将 不会衬着到视图中。它能为其子组件激活分外的搜检和正告。

注重

<StrictMode />搜检只在开辟形式下运转;它们不会影响临盆构建。

虽然严厉的形式不能够捕捉一切的题目(比方某些范例的改动),但它能够协助很多人。假如您在严厉的形式下看到正告,这些事变很能够会致使异步衬着的毛病。

在16.3版本中,StrictMode协助:

  1. 辨认具有不安全生命周期钩子的组件。
  2. 关于遗留字符串ref API用法的正告。
  3. 检测意想不到的副作用
    原文作者:司徒正美
    原文地址: https://segmentfault.com/a/1190000014083970
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞