首页 > 解决方案 > 从 componentWillReceiveProps 迁移到 getDerivedStateFromProps

问题描述

我正在学习 reactjs,我使用方法 componentWillReceiveProps (cWRP) 编写了组件,但我读到它已被弃用,它必须替换为 getDerivedStateFromProps (gDSFP) - https://en.reactjs.org/blog/2018/06/07/你可能不需要派生的state.html
请注意,以下代码仅用于说明我的问题和疑问。它不是完整的代码。
App.js 文件:

import React from 'react';
import './App.css';

import Display from './component.js'

class App extends React.Component {

  state={resetCounter:false}

  resetCounter= () => this.setState( {resetCounter: true} );

  render() {
      return (
      <div className="App">
        <header className="App-header">
          <Display resetCounter={this.state.resetCounter}></Display>
          <div>
           <p></p><p></p>
           <button onClick={this.resetCounter}>Reset</button>
          </div>
        </header>
      </div>
    );
  }

  componentDidUpdate () {
    if (this.state.resetCounter!==false)
      this.setState( {resetCounter: false} );
  }

}

export default App;

组件.js 文件

import React from 'react'

class Display extends React.Component {

  constructor() {
    super();
    this.state = this.resetState();
    this.state.generalCounter=0;
  } 

  /* method to avoid code duplication in constructor and cWRP
   could not be used with getDerivedStateFromProps */
  resetState = () => ({resettableCounter: 0,}); 

  componentWillReceiveProps(nextProps) {
    if (nextProps.resetCounter===true) 
      this.setState(this.resetState())
  }

  render() {
    return (
        <>
        <div>
        <div>general counter : {this.state.generalCounter}</div>
        <div>resettable counter : {this.state.resettableCounter}</div>
        </div>
        <div>
            <button onClick={this.incCounters}>+</button>
            <button onClick={this.decCounters}>-</button>
        </div>
        </>
    )
  }

  incCounters= () => this.setState(
    {
      resettableCounter: this.state.resettableCounter+1,
      generalCounter: this.state.generalCounter+1 
    }
  )

  decCounters= () => this.setState(
    {
      resettableCounter: this.state.resettableCounter-1,
      generalCounter: this.state.generalCounter-1
    }
  )

}

export default Display

在元件的状态下,有可复位部分和不可复位部分。一种方法resetState用于避免构造函数和 cWRP 中的代码重复。
为了用 gDSFP 替换 cWRP,我写了一个类方法,因为在 gDSFP 中不能调用实例方法(this不可用)

... 

  constructor() {
    super();
    this.state = Display.resetState();
    this.state.generalCounter=0;
  } 

  static resetState () {
    return ({resettableCounter: 0,}); 
  }

  static getDerivedStateFromProps(nextProps) {
    if (nextProps.resetCounter === true) {
      return Display.resetState();
    } else {
      return null;
    }
  }

...

使用此解决方案,很容易修改我的所有组件,但我不确定这是一个好方法。
我想知道我是否有一个误解,是否应该重写我的组件以将它们分成完全受控的组件和带有密钥的完全不受控的组件(https://en.reactjs.org/blog/2018/06/07/you-probably -dont-need-derived-state.html#preferred-solutions)。
例如,在这种情况下,我是否必须写:

  1. 一 用于可复位计数器的完全不受控制的组件
  2. 一个 完全控制一个不可复位计数器
  3. 带有 +/- 按钮的父组件来呈现它们。

我问这个问题是因为在某些情况下,这将是很多工作,所以我想在继续之前确定。

标签: reactjs

解决方案


gdsfp如果您的组件依赖于一些您无法控制的外部道具(例如返回的 JSON 或 3rd 方渲染道具组件等),您可能希望将版本保留在您的帖子中。

看起来您可以完全控制传递给Display. 您可以将初始resettableCounter值向下传递给Display.

优点是双重的。

  1. 你的Display道具展示了它的Display作用 - 使其更具描述性/可读性。
  2. 它更容易维护,因为您不必处理数据。

对于您的特定情况,Fully uncontrolled component with a key似乎更有意义,因为Display应该接受要显示的初始值,但负责管理reseetableCounter.


推荐阅读