从props响应组件初始化状态

在React中,这两种实现之间有什么真正的区别?一些朋友告诉我,FirstComponent是模式,但是我不明白为什么。SecondComponent似乎更简单,因为渲染仅被调用一次。

第一:

import React, { PropTypes } from 'react'

class FirstComponent extends React.Component {

  state = {
    description: ''
  }

  componentDidMount() {
    const { description} = this.props;
    this.setState({ description });
  }

  render () {
    const {state: { description }} = this;    
    return (
      <input type="text" value={description} /> 
    );
  }
}

export default FirstComponent;

第二:

import React, { PropTypes } from 'react'

class SecondComponent extends React.Component {

  state = {
    description: ''
  }

  constructor (props) => {
    const { description } = props;
    this.state = {description};
  }

  render () {
    const {state: { description }} = this;    
    return (
      <input type="text" value={description} />   
    );
  }
}

export default SecondComponent;

更新:我将setState()更改为this.state = {}(感谢乔伊斯),但是,我仍然看不到区别。一个比另一个好吗?

阿飞Sam2020/03/11 10:52:48

您可以使用componentWillReceiveProps。

constructor(props) {
    super(props);
    this.state = {
      productdatail: ''
    };
  }

    componentWillReceiveProps(nextProps){
        this.setState({ productdatail: nextProps.productdetailProps })
    }
神乐蛋蛋2020/03/11 10:52:47

像这样在构造函数中设置状态数据

constructor(props) {
    super(props);
    this.state = {
      productdatail: this.props.productdetailProps
    };
  }

如果您通过道具在componentDidMount()方法中进行设置,它将无法正常工作。

Tom小小蛋蛋2020/03/11 10:52:47

您可以key在需要时使用值来重置状态,通过props来声明这不是一个好习惯,因为您在一个地方拥有不受控制的组件。数据应放在一个地方处理,请参阅以下 https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html#recommendation-fully-uncontrol-component-with-a -键

逆天Stafan2020/03/11 10:52:47

您不需要调用setState组件constructor- this.state直接设置是惯用法

class FirstComponent extends React.Component {

  constructor(props) {
    super(props);

    this.state = {
      x: props.initialX
    };
  }
  // ...
}

参见React docs-向类添加局部状态

您描述的第一种方法没有任何优势。它将在首次安装组件之前立即进行第二次更新。

Mandy村村2020/03/11 10:52:47

如果您直接通过道具初始化状​​态,它将在React 16.5中显示警告(2018年9月5日)

GO西里2020/03/11 10:52:47

更新了React 16.3 alpha static getDerivedStateFromProps(nextProps, prevState)文档),以替代componentWillReceiveProps

实例化组件之后以及接收到新的道具时,将调用getDerivedStateFromProps。它应该返回一个对象来更新状态,或者返回null来指示新道具不需要任何状态更新。

请注意,如果父组件导致您的组件重新渲染,则即使道具没有更改,也会调用此方法。如果只想处理更改,则可能需要比较新值和先前值。

https://reactjs.org/docs/react-component.html#static-getderivedstatefromprops

它是静态的,因此它不能直接访问this(但是确实可以访问prevState,它可以存储通常附加到的内容,this例如refs

编辑以在评论中反映@nerfologist的更正

猴子十三2020/03/11 10:52:47

如果要添加所有道具以声明并保留相同的名称,则可以使用如下所示的简短形式。

constructor(props) {
    super(props);
    this.state = {
       ...props
    }
    //...
}
逆天古一Mandy2020/03/11 10:52:47

应该注意的是,复制永远不会更改为状态的属性是一种反模式(在这种情况下,只需直接访问.props即可)。如果您有一个状态变量最终会更改,但以.props中的值开头,则您甚至不需要构造函数调用-这些局部变量在调用父级的构造函数之后初始化:

class FirstComponent extends React.Component {
  state = {
    x: this.props.initialX,
    // You can even call functions and class methods:
    y: this.someMethod(this.props.initialY),
  };
}

这是等效于下面@joews中答案的简写。它似乎只能在最新版本的es6编译器上使用,在某些Webpack设置中我遇到了问题。如果这对您不起作用,则可以尝试添加babel插件babel-plugin-transform-class-properties,也可以使用下面@joews提供的非简写版本。