简体   繁体   English

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

[英]React component initialize state from props

In React, are there any real differences between these two implementations?在 React 中,这两种实现之间有什么真正的区别吗? Some friends tell me that the FirstComponent is the pattern, but I don't see why.有些朋友告诉我 FirstComponent 是模式,但我不明白为什么。 The SecondComponent seems simpler because the render is called only once. SecondComponent 看起来更简单,因为渲染只被调用一次。

First:首先:

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;

Second:第二:

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;

Update: I changed setState() to this.state = {} (thanks joews), However, I still don't see the difference.更新:我将 setState() 更改为 this.state = {} (感谢 joews),但是,我仍然没有看到区别。 Is one better than other?一个比另一个更好吗?

It should be noted that it is an anti-pattern to copy properties that never change to the state (just access .props directly in that case).应该注意的是,复制永远不会更改为状态的属性是一种反模式(在这种情况下直接访问 .props)。 If you have a state variable that will change eventually but starts with a value from .props, you don't even need a constructor call - these local variables are initialized after a call to the parent's constructor:如果你有一个最终会改变但以 .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),
  };
}

This is a shorthand equivalent to the answer from @joews below.这是相当于下面@joews 的答案的速记。 It seems to only work on more recent versions of es6 transpilers, I have had issues with it on some webpack setups.它似乎只适用于更新版本的 es6 转译器,我在某些 webpack 设置上遇到了问题。 If this doesn't work for you, you can try adding the babel plugin babel-plugin-transform-class-properties , or you can use the non-shorthand version by @joews below.如果这对您不起作用,您可以尝试添加 babel 插件babel-plugin-transform-class-properties ,或者您可以使用下面@joews 的非速记版本。

You don't need to call setState in a Component's constructor - it's idiomatic to set this.state directly:您不需要在组件的constructor调用setState - 直接设置this.state是惯用的:

class FirstComponent extends React.Component {

  constructor(props) {
    super(props);

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

See React docs - Adding Local State to a Class .请参阅React 文档 - 将本地状态添加到类

There is no advantage to the first method you describe.您描述的第一种方法没有任何优势。 It will result in a second update immediately before mounting the component for the first time.它将在第一次安装组件之前立即进行第二次更新。

Update for React 16.3 alpha introduced static getDerivedStateFromProps(nextProps, prevState) ( docs ) as a replacement for componentWillReceiveProps . React 16.3 alpha 的更新引入了static getDerivedStateFromProps(nextProps, prevState) ( docs ) 作为componentWillReceiveProps的替代品。

getDerivedStateFromProps is invoked after a component is instantiated as well as when it receives new props. getDerivedStateFromProps 在一个组件被实例化之后以及当它接收到新的 props 时被调用。 It should return an object to update state, or null to indicate that the new props do not require any state updates.它应该返回一个对象来更新状态,或者返回 null 来表示新的 props 不需要任何状态更新。

Note that if a parent component causes your component to re-render, this method will be called even if props have not changed.请注意,如果父组件导致您的组件重新渲染,即使 props 未更改,也会调用此方法。 You may want to compare new and previous values if you only want to handle changes.如果您只想处理更改,您可能想要比较新值和以前的值。

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

It is static, therefore it does not have direct access to this (however it does have access to prevState , which could store things normally attached to this eg refs )它是静态的,因此它不能直接访问this (但是它可以访问prevState ,它可以存储通常附加到this东西,例如refs

edited to reflect @nerfologist's correction in comments编辑以反映@nerfologist 在评论中的更正

You could use the short form like below if you want to add all props to state and retain the same names.如果您想将所有道具添加到状态并保留相同的名称,您可以使用如下的简短形式。

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

YOU HAVE TO BE CAREFUL when you initialize state from props in constructor.当您从构造函数中的props初始化state时,您必须小心。 Even if props changed to new one, the state wouldn't be changed because mount never happen again.即使props变成新的,状态也不会改变,因为 mount 再也不会发生了。 So getDerivedStateFromProps exists for that.所以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} /> 
        );
    }
}

Or use key props as a trigger to initialize:或者使用key props作为触发器来初始化:

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

In the code above, if something changed, then SecondComponent will re-mount as a new instance and state will be initialized by props .在上面的代码中,如果有something改变,那么SecondComponent将作为一个新实例重新挂载state将被props初始化。

set the state data inside constructor like this像这样在构造函数中设置状态数据

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

it will not going to work if u set in side componentDidMount() method through props.如果你通过 props 在 side componentDidMount()方法中设置,它就不会工作。

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

you could use key value to reset state when need, pass props to state it's not a good practice , because you have uncontrolled and controlled component in one place.您可以在需要时使用key重置状态,将道具传递给状态这不是一个好习惯,因为您在一个地方有不受控制和受控的组件。 Data should be in one place handled read this https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html#recommendation-fully-uncontrolled-component-with-a-key数据应该在一个地方处理阅读这个https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html#recommendation-fully-uncontrolled-component-with-a -键

You can use componentWillReceiveProps.您可以使用 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