繁体   English   中英

React组件从道具初始化状​​态

[英]React component initialize state from 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 = {} (感谢 joews),但是,我仍然没有看到区别。 一个比另一个更好吗?

应该注意的是,复制永远不会更改为状态的属性是一种反模式(在这种情况下直接访问 .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 的非速记版本。

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

class FirstComponent extends React.Component {

  constructor(props) {
    super(props);

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

请参阅React 文档 - 将本地状态添加到类

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

React 16.3 alpha 的更新引入了static getDerivedStateFromProps(nextProps, prevState) ( docs ) 作为componentWillReceiveProps的替代品。

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

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

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

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

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

如果您想将所有道具添加到状态并保留相同的名称,您可以使用如下的简短形式。

constructor(props) {
    super(props);
    this.state = {
       ...props
    }
    //...
}

当您从构造函数中的props初始化state时,您必须小心。 即使props变成新的,状态也不会改变,因为 mount 再也不会发生了。 所以getDerivedStateFromProps存在。

class FirstComponent extends React.Component {
    state = {
        description: ""
    };
    
    static getDerivedStateFromProps(nextProps, prevState) {
        if (prevState.description !== nextProps.description) {
          return { description: nextProps.description };
        }
    
        return null;
    }

    render() {
        const {state: {description}} = this;    

        return (
            <input type="text" value={description} /> 
        );
    }
}

或者使用key props作为触发器来初始化:

class SecondComponent extends React.Component {
  state = {
    // initialize using props
  };
}
<SecondComponent key={something} ... />

在上面的代码中,如果有something改变,那么SecondComponent将作为一个新实例重新挂载state将被props初始化。

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

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

如果你通过 props 在 side componentDidMount()方法中设置,它就不会工作。

如果你直接从 props init state,它会在 React 16.5(2018 年 9 月 5 日)中显示警告

您可以在需要时使用key重置状态,将道具传递给状态这不是一个好习惯,因为您在一个地方有不受控制和受控的组件。 数据应该在一个地方处理阅读这个https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html#recommendation-fully-uncontrolled-component-with-a -键

您可以使用 componentWillReceiveProps。

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

componentWillReceiveProps(nextProps){
    this.setState({ productdatail: nextProps.productdetailProps })
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM