React、ES6-getInitialStateはプレーンなJavaScriptクラスで定義されました


115

次のコンポーネント(radioOther.jsx)があります。

 'use strict';

 //module.exports = <-- omitted in update

   class RadioOther extends React.Component {

     // omitted in update 
     // getInitialState() {
     //    propTypes: {
     //        name: React.PropTypes.string.isRequired
     //    }
     //    return {
     //       otherChecked: false
     //   }
     // }

     componentDidUpdate(prevProps, prevState) {
         var otherRadBtn = this.refs.otherRadBtn.getDOMNode();

         if (prevState.otherChecked !== otherRadBtn.checked) {
             console.log('Other radio btn clicked.')
             this.setState({
                 otherChecked: otherRadBtn.checked,
             });
         }
     }

     onRadChange(e) {
         var input = e.target;
         this.setState({
             otherChecked: input.checked
         });
     }

     render() {
         return (
             <div>
                 <p className="form-group radio">
                     <label>
                         <input type="radio"
                                ref="otherRadBtn"
                                onChange={this.onRadChange}
                                name={this.props.name}
                                value="other"/>
                         Other
                     </label>
                     {this.state.otherChecked ?
                         (<label className="form-inline">
                             Please Specify:
                             <input
                                 placeholder="Please Specify"
                                 type="text"
                                 name="referrer_other"
                                 />
                         </label>)
                         :
                         ('')
                     }
                 </p>
             </div>
         )
     }
 };

ECMAScript6を使用する前はすべて問題ありませんでしたが、今はエラーが1つ、警告が1つあり、フォローアップの質問があります。

エラー:キャッチされないTypeError:nullのプロパティ 'otherChecked'を読み取れません

警告: getInitialStateは、プレーンなJavaScriptクラスであるRadioOtherで定義されています。これは、React.createClassを使用して作成されたクラスでのみサポートされます。代わりに状態プロパティを定義するつもりでしたか?


  1. エラーがどこにあるか誰でも見ることができます、それはDOMの条件ステートメントが原因であることがわかりますが、どうやら私はその初期値を正しく宣言していないのですか?

  2. getInitialStateを静的にする必要があります

  3. getInitialStateが正しくない場合、プロップタイプを宣言する適切な場所はどこですか?

更新:

   RadioOther.propTypes = {
       name: React.PropTypes.string,
       other: React.PropTypes.bool,
       options: React.PropTypes.array }

   module.exports = RadioOther;

@ssorallen、このコード:

     constructor(props) {
         this.state = {
             otherChecked: false,
         };
     }

を生成し"Uncaught ReferenceError: this is not defined"、以下はそれを修正します

     constructor(props) {
     super(props);
         this.state = {
             otherChecked: false,
         };
     }

しかし今、他のボタンをクリックするとエラーが発生します:

Uncaught TypeError: Cannot read property 'props' of undefined


1
ES6クラスの他の変更は、方法はあなたのような関数を渡すとき意味、「自動バインド」インスタンスにはないということですonChange={this.onRadChange}this時にインスタンスを参照していないonRadChangeと呼ばれています。コールバックをバインドするrenderか、コンストラクターでバインドする必要がありますonChange={this.onRadChange.bind(this)}
ロス・アレン

回答:


239
  • getInitialStateES6クラスでは使用されません。代わりthis.stateに、コンストラクタで割り当てます。
  • propTypes 静的クラス変数であるか、クラスに割り当てられている必要があります。コンポーネントインスタンスには割り当てられません。
  • ES6クラスでは、メンバーメソッドは「自動バインド」されていません。コールバックとして使用されるメソッドの場合、クラスプロパティ初期化子を使用するか、コンストラクターでバインドされたインスタンスを割り当てます。
export default class RadioOther extends React.Component {

  static propTypes = {
    name: React.PropTypes.string.isRequired,
  };

  constructor(props) {
    super(props);
    this.state = {
      otherChecked: false,
    };
  }

  // Class property initializer. `this` will be the instance when
  // the function is called.
  onRadChange = () => {
    ...
  };

  ...

}

ES6クラス:関数をクラスに変換することに関するReactのドキュメントで詳細を参照してください。


一年後、あなたはあなたが得ることを見つけるかもしれません:Uncaught TypeError: Cannot read property 'bind' of undefinedエラー何かアイデア?
Jamie Hutber、2016年

@JamieHutberコードで新しい質問を作成できますか?メソッドがクラスで定義されている場合、そのエラーが発生する理由はわかりません。
ロス・アレン

提案をありがとう、@ KennethWorden。Reactドキュメントの問題を公開しました:github.com/facebook/react/issues/7746
Ross Allen

「それらを所定の位置にバインドする」とは、上に示したように矢印関数を使用することを意味しますか?もちろん、それでうまくいきます。ああ、javascript!
jomofrodo 2016年

@jomofrodoそれはあいまいです、それを指摘してくれてありがとう。私はrenderあなたがのようなことをすることができることを意味しましたがonClick={this.doFoo.bind(this)}、それはrender頻繁に呼び出され、各呼び出しで新しい関数を作成するため、バインドする最も効率の悪い方法であるため、意図的にコードに含めませんでした。答えからその言語を削除します。
ロス・アレン

4

ロスの答えに追加。

onChangeプロパティで新しいES6矢印関数を使用することもできます

機能的this.onRadChange = this.onRadChange.bind(this);にはコンストラクタでの定義と同等ですが、私の意見ではより簡潔です。

あなたの場合、ラジオボタンは以下のようになります。

<input type="radio"
       ref="otherRadBtn"
       onChange={(e)=> this.onRadChange(e)}
       name={this.props.name}
       value="other"/>

更新

この「より簡潔な」メソッドは、render()メソッドが呼び出されるたびに新しい関数を生成するため、@ Ross Allenの回答で述べられているオプションよりも効率が悪い


1
このソリューションは機能的には正しいですが、render(何度も呼び出される可能性がある)への呼び出しごとに新しい関数を作成します。コンストラクターでクラスプロパティ初期化子またはバインディングを使用することにより、コンポーネントの構築時に1つの新しいバインドされた関数のみが作成され、中に新しい関数は作成されませんrender
ロス・アレン

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.