web-dev-qa-db-ja.com

反応コンポーネントは小道具から状態を初期化します

Reactでは、これら2つの実装の間に実際の違いはありますか? 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)。しかし、それでも違いはわかりません。他よりも優れていますか?

124
Levy Moreira

状態に変化しないプロパティをコピーすることはアンチパターンであることに注意してください(その場合は直接.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 transpilerでしか動作しないようですが、いくつかのwebpackの設定で問題がありました。これがうまくいかない場合は、babelプラグインbabel-plugin-transform-class-propertiesを追加してみるか、下記の@joewsの簡易版を使用してください。

123
Zane Hooper

コンポーネントのsetState内でconstructorを呼び出す必要はありません。this.stateを直接設定するのは慣用的なことです。

class FirstComponent extends React.Component {

  constructor(props) {
    super(props);

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

React docs - クラスへのローカル状態の追加を参照してください

最初に説明した方法には利点がありません。初めてコンポーネントをマウントする直前に2回目の更新が行われます。

112
joews

React 16.3用の更新 alphaはcomponentWillReceivePropsの代わりにstatic getDerivedStateFromProps(nextProps, prevState)docs )を導入しました。

getDerivedStateFromPropsは、コンポーネントがインスタンス化された後、およびコンポーネントが新しい小道具を受け取ったときに呼び出されます。オブジェクトを返して状態を更新するか、nullを返して新しい小道具が状態の更新を必要としないことを示します。

親コンポーネントによってコンポーネントが再レンダリングされる場合、小道具が変更されていなくてもこのメソッドが呼び出されることに注意してください。変更だけを処理したい場合は、新しい値と以前の値を比較することをお勧めします。

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

静的なので、thisに直接アクセスすることはできません(ただし、prevStateにアクセスすることで、通常はthisにアタッチされているものを格納できます。例:refs

コメントに@ nerfologistの修正を反映するように編集されています

25
Ashley Coolman

すべての小道具をstateに追加して同じ名前を保持する場合は、次のような短い形式を使用できます。

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

小道具から直接状態を初期化すると、React 16.5(2018年9月5日)に警告が表示されます。

1
sujithklr93

このようにコンストラクタ内の状態データを設定します

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

uがpropsを介してside componentDidMount()メソッドに設定されている場合、機能しません。

必要に応じて状態をリセットするためにkey値を使用することができます。制御されていないコンポーネントと制御されたコンポーネントが1か所にあるため、小道具を渡すことはお勧めできません。データは一箇所で扱われるべきですこれを読んでください https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html#recommendation-fully-uncontrolled-component-with -かぎ

0