web-dev-qa-db-ja.com

反応 - 制御されてない入力を変更する

私は一つの制御された入力を持つと信じているフォームを持つ単純な反応コンポーネントを持っています:

import React from 'react';

export default class MyForm extends React.Component {
    constructor(props) {
        super(props);
        this.state = {}
    }

    render() {
        return (
            <form className="add-support-staff-form">
                <input name="name" type="text" value={this.state.name} onChange={this.onFieldChange('name').bind(this)}/>
            </form>
        )
    }

    onFieldChange(fieldName) {
        return function (event) {
            this.setState({[fieldName]: event.target.value});
        }
    }
}

export default MyForm;

アプリケーションを実行すると、次のような警告が表示されます。

警告:MyFormは、制御されるtext型の制御されていない入力を変更しています。入力要素は、制御されていない状態から制御されている状態(またはその逆)に切り替わるべきではありません。コンポーネントの寿命の間、制御されているか制御されていない入力要素を使用するかを決定します。

価値があるので私の入力は制御されていると思います。何がおかしいのですか。

私はReactを使っています 15.1.0

220
alexs333

価値があるので私の入力は制御されていると思います。

入力を制御するには、その値が状態変数の値に対応している必要があります。

this.state.nameが最初に設定されていないため、この条件は最初の例では満たされていません。したがって、入力は最初は制御されていません。 onChangeハンドラーが初めてトリガーされると、this.state.nameが設定されます。その時点で、上記の条件が満たされ、入力が制御されていると見なされます。制御されていない状態から制御された状態へのこの移行により、上記のエラーが発生します。

コンストラクタでthis.state.nameを初期化することによって:

例えば.

this.state = { name: '' };

入力が最初から制御され、問題が修正されます。その他の例については React Controlled Components を参照してください。

このエラーに関係なく、デフォルトのエクスポートは1つだけです。上記のコードには2つあります。

330
fvgs

最初にコンポーネントをレンダリングするときは、this.state.nameは設定されていないため、undefinedと評価され、最終的にvalue={undefined}inputに渡します。

ReactDOMがフィールドが制御されているかどうかをチェックするとき、 それはvalue != null であるかどうかをチェックします(!=ではなく!==である)、そしてJavaScriptではundefined == nullから制御されていないと判断します。

そのため、onFieldChange()が呼び出されると、this.state.nameが文字列値に設定され、入力は制御されなくなります。

this.state = {name: ''}をコンストラクターで行うと、'' != nullなので、入力には常に値が入り、そのメッセージは消えます。

91
Leigh Brenecki

もう1つの方法は、次のように入力内のデフォルト値を設定することです。

 <input name="name" type="text" value={this.state.name || ''} onChange={this.onFieldChange('name').bind(this)}/>
35
JpCrow

私は他の人がすでにこれに答えていることを知っています。しかし、ここで非常に重要な要素の1つは同様の問題を経験している他の人々を助けるかもしれません:

入力フィールドにonChangeハンドラを追加する必要があります(例えばtextField、チェックボックス、ラジオなど)。そして常に次のようにonChangeハンドラを通してアクティビティを処理します。

<input ... onChange={ this.myChangeHandler} ... />

checkbox で作業しているときは、checked状態を!!で処理する必要があります。

<input type="checkbox" checked={!!this.state.someValue} onChange={.....} >

参照: https://github.com/facebook/react/issues/6779#issuecomment-326314716

6
Muhammad Hannan

コンストラクタでフィールド値を ""(空の文字列)に設定することによる1つの潜在的なマイナス面は、フィールドがオプションのフィールドであり、未編集のまま残されることです。フォームを投稿する前にメッセージを変換しない限り、フィールドはNULLではなく空の文字列としてデータストレージに保持されます。

この代替手段は空の文字列を避けます。

constructor(props) {
    super(props);
    this.state = {
        name: null
    }
}

... 

<input name="name" type="text" value={this.state.name || ''}/>
5
Greg R Taylor

入力にonChange={this.onFieldChange('name').bind(this)}を使用するときは、stateフィールドの空の文字列をpropertyフィールドの値として宣言する必要があります。

間違った方法:

this.state ={
       fields: {},
       errors: {},
       disabled : false
    }

正しい方法:

this.state ={
       fields: {
         name:'',
         email: '',
         message: ''
       },
       errors: {},
       disabled : false
    }
3
KARTHIKEYAN.A

コンポーネントの小道具が状態として渡された場合は、入力タグにデフォルト値を設定してください。

<input type="text" placeholder={object.property} value={object.property ? object.property : ""}>
2
Emperor Krauser

これの更新。 Reactフックにはconst [name、setName] = useState( "")を使用します

2
Jordan Mullen

私の場合、私は本当に些細なことを見逃していました。

<input value={state.myObject.inputValue} />

私が警告を受けたときの私の状態は次のとおりでした。

state = {
   myObject: undefined
}

自分の状態を 自分の値の入力を参照する に変更することで、私の問題は解決しました:

state = {
   myObject: {
      inputValue: ''
   }
}

初期状態では 'name'プロパティに値を設定してください。

this.state={ name:''};
1

この問題を解決する簡単な解決策は、デフォルトで空の値を設定することです。

<input name='myInput' value={this.state.myInput || ''} onChange={this.handleChange} />
0

これは通常、アプリケーションの起動時にフィールドの値を制御していない場合、および何らかのイベントや機能の起動後や状態の変更後に入力フィールドの値を制御しようとしている場合にのみ発生します。

入力を制御できず、それから制御できるというこの移行は、そもそも問題が発生する原因となります。

これを回避する最善の方法は、コンポーネントのコンストラクター内の入力に対して何らかの値を宣言することです。 input要素がアプリケーションの先頭からの値を持つようにします。

0