web-dev-qa-db-ja.com

コンストラクターで状態を定義するか、プロパティ初期化子を使用する方が良いですか?

this babelのドキュメントによると、ES6 +をReactとともに使用する正しい方法は、次のような初期コンポーネントです。

class Video extends React.Component {
  static defaultProps = {
    autoPlay: false,
    maxLoops: 10,
  }
  static propTypes = {
    autoPlay: React.PropTypes.bool.isRequired,
    maxLoops: React.PropTypes.number.isRequired,
    posterFrameSrc: React.PropTypes.string.isRequired,
    videoSrc: React.PropTypes.string.isRequired,
  }
  state = {
    loopsRemaining: this.props.maxLoops,
  }
}

しかし、Dan Abramov自身の React DnD モジュールのようないくつかの公式例では、ES6 +を使用していますが、コンストラクター内で状態を定義しています:

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

現在、Reactに多大な貢献をしているDan Abramovは、おそらくコンストラクターの外で状態を定義できることを知っていますが、それでもコンストラクター内でそれを行うことを選択しています。

だから、どちらの方が良いのか、なぜだろうかと思っています。

53
abustamam

個人的な好みの問題だと思います。変換された出力は、セマンティクスの点では同じです。

68
ctrlplusb

クラスフィールドの提案 はコンストラクター本体コードの構文糖衣であるため、これらは同等です。

明示的なコンストラクター(一時的なローカル変数の作成など)が必要ない場合は、クラスフィールドを優先してconstructorを省略できます。

明示的なコンストラクターの問題は、super引数(props)がしばしば誤って省略されることです。これにより、問題が発生する可能性があります。

constructor() {
    super();
    this.state = { foo: this.props.foo } // this.props is undefined
}

明示的なコンストラクターは、読みやすくするのに役立ちます。メソッドは従来のconstructorの下に配置され、矢印のプロパティもあります。クラスフィールドはリストされた順序で割り当てられるため、これは意図したとおりには機能しません。

state = { foo: { method: this.someMethod } } // this.someMethod is undefined

someMethod = () => ...;

この場合、明示的なコンストラクターはより読みやすいコードになる可能性があります。

constructor(props) {
    super(props);

    // <-- this is the place where this.someMethod is really assigned

    this.state = { foo: { method: this.someMethod } }
}

someMethod = () => ...;
8
Estus Flask

Danのコードには実際には微妙なバグがあるため、可能な限りイニシャライザを使用することをお勧めします。 Reactコンポーネントコンストラクターは、propsとcontextの2つの引数を取ります。彼はそれを親コンストラクターに渡さず、それを必要とする他の開発者によって簡単に見落とされる可能性があります。

初期化子がコンストラクタの引数に依存する場合など、選択の余地がない場合があるため、すべての引数を親に渡すことを忘れないでください。

いくつかのことを試した後、Reactには、私が考えていた問題はありません。親のコンストラクタに必要なものを渡すことができます。それは問題ありません。例えば:

class MyComponent extends React.Component {
  constructor(props) {
    super({})
  }

  render() {
    // this.props will still be set correctly here
  }
}

親コンストラクターを呼び出さなくても済むように、イニシャライザーを使用することをお勧めします。

1
Gunchars