コンポーネントがReactJSの制御されたエラーになるようにタイプテキストの制御されていない入力を変更しています


331

警告:コンポーネントは、制御されるタイプのテキストの非制御入力を変更しています。入力要素は、非制御から制御へ(またはその逆)に切り替えないでください。コンポーネントの有効期間中、制御された入力要素と制御されていない入力要素のどちらを使用するかを決定します。*

以下は私のコードです:

constructor(props) {
  super(props);
  this.state = {
    fields: {},
    errors: {}
  }
  this.onSubmit = this.onSubmit.bind(this);
}

....

onChange(field, e){
  let fields = this.state.fields;
  fields[field] = e.target.value;
  this.setState({fields});
}

....

render() {
  return(
    <div className="form-group">
      <input
        value={this.state.fields["name"]}
        onChange={this.onChange.bind(this, "name")}
        className="form-control"
        type="text"
        refs="name"
        placeholder="Name *"
      />
      <span style={{color: "red"}}>{this.state.errors["name"]}</span>
    </div>
  )
}

2
fields状態の初期値は何ですか?
Mayank Shukla 2017

2
コンストラクタ(プロップ){スーパー(プロップ); this.state = {fields:{}、errors:{}} this.onSubmit = this.onSubmit.bind(this); }
Riya Kapuria 2017年

回答:


650

その理由は、あなたが定義した状態で:

this.state = { fields: {} }

フィールドは空のオブジェクトとして表示this.state.fields.nameされるため、最初のレンダリング中はundefinedとなり、入力フィールドの値は次のようになります。

value={undefined}

そのため、入力フィールドは制御されなくなります。

入力に値を入力するとfields、状態は次のように変更されます。

this.state = { fields: {name: 'xyz'} }

そのとき、入力フィールドは制御されたコンポーネントに変換されます。そのため、エラーが発生します。

コンポーネントが、制御するタイプのテキストの非制御入力を変更しています。

可能な解決策:

1- fields状態を次のように定義します。

this.state = { fields: {name: ''} }

2-または、次のような短絡評価を使用して値のプロパティを定義します。

value={this.state.fields.name || ''}   // (undefined || '') = ''

5
未定義が「制御されていない」のに対し、後者が「制御されている」という理由はありますか?これらはどういう意味ですか?
プラシャントスブラマニアン

2
理由は、''有効な文字列値です。そのため、'''xyz'に変更しても、入力タイプは制御された手段から制御された手段に変わりません。しかし、undefinedto xyz型の場合、制御されていない状態から制御されている状態に変わります。
Mayank Shukla

1
これは私のために働いてくれてありがとう:value={this.state.fields.name || ''}
ボブ

1
値が未定義になると、入力が自動的に制御されなくなることを知りませんでした。すでに私の問題を修正
Adrian Serna

1
すごい!公式ドキュメントでこれが言及されていなかったため、または私は盲目ですか?ソースへのリンクをお願いします:)
Dheeraj

34

に変更valueするdefaultValueと解決します。

defaultValue初期ロード専用です。初期化するinput場合はを使用する必要がありますが、defaultValueを使用stateして値を変更する場合はを使用する必要がありますvalue。読む本を多くのため。

私はその警告を取り除くために使用value={this.state.input ||""}inputました。


2
ありがとうございました!私はこの問題に遭遇し、他の解決策は私には当てはまりませんでしたが、この解決策は役に立ちました。
PepperAddict

14

コンポーネント内に次のように入力ボックスを配置します。

<input className="class-name"
              type= "text"
              id="id-123"
              value={ this.state.value || "" }
              name="field-name"
              placeholder="Enter Name"
              />

13

単純に、最初に初期状態を設定する必要があります

初期状態を設定しないと、reactはそれを非制御コンポーネントとして扱います


10

受け入れられた回答に加えて、inputタイプのcheckboxまたはを使用している場合はradiochecked属性もnullまたは未定義でチェックする必要があることがわかりました。

<input
  id={myId}
  name={myName}
  type="checkbox" // or "radio"
  value={myStateValue || ''}
  checked={someBoolean ? someBoolean : false}
  />

また、TS(またはBabel)を使用している場合は、論理OR演算子の代わりに、nullish合体を使用できます。

value={myStateValue ?? ''}
checked={someBoolean ?? false}

8

最初に現在の状態を設定 ...this.state

これは、新しい状態を割り当てるときに未定義になる可能性があるためです。現在の状態も抽出する状態を設定することで修正されます

this.setState({...this.state, field})

状態にオブジェクトがある場合は、次のように状態を設定する必要があります。ユーザーオブジェクト内でユーザー名を設定する必要があるとします。

this.setState({user:{...this.state.user, ['username']: username}})

1
私が理解している限り、setStateは既にフィールドのみをオーバーライドしているため、最初のケースでは、割り当てを分解する必要はありません。2番目の状態では、setStateがサブオブジェクトのホールセールを置き換えるため、必要になる場合があります。
Kzqai

6
const [name, setName] = useState()

テキストフィールドに入力するとすぐにエラーが発生します

const [name, setName] = useState('') // <-- by putting in quotes 

この文字列の例の問題を修正します。


2

フィールドで複数の入力を使用する場合は、次のようにします。次に例を示します。

class AddUser extends React.Component {
   constructor(props){
     super(props);

     this.state = {
       fields: { UserName: '', Password: '' }
     };
   }

   onChangeField = event => {
    let name = event.target.name;
    let value = event.target.value;
    this.setState(prevState => {
        prevState.fields[name] =  value;
        return {
           fields: prevState.fields
        };
    });
  };

  render() { 
     const { UserName, Password } = this.state.fields;
     return (
         <form>
             <div>
                 <label htmlFor="UserName">UserName</label>
                 <input type="text" 
                        id='UserName' 
                        name='UserName'
                        value={UserName}
                        onChange={this.onChangeField}/>
              </div>
              <div>
                  <label htmlFor="Password">Password</label>
                  <input type="password" 
                         id='Password' 
                         name='Password'
                         value={Password}
                         onChange={this.onChangeField}/>
              </div>
         </form>
     ); 
  }
}

次の場所で問題を検索してください:

onChangeField = event => {
    let name = event.target.name;
    let value = event.target.value;
    this.setState(prevState => {
        prevState.fields[name] =  value;
        return {
            fields: prevState.fields
        };
    });
};

1

React Hooksを使用する場合も、初期値を設定することを忘れないでください。
使ってい<input type='datetime-local' value={eventStart} />てイニシャルeventStart

const [eventStart, setEventStart] = useState();
代わりに
const [eventStart, setEventStart] = useState('');

括弧内の空の文字列は違います。
また、私が行うように送信後にフォームをリセットする場合も、空の括弧ではなく空の文字列にフォームを設定する必要があります。

これはこのトピックへの私の小さな貢献です。多分それは誰かを助けるでしょう。


0

私の場合、Mayank Shuklaのトップアンサーが言っていることはほとんどそれでした。唯一の詳細は、私の状態は私が定義していた特性を完全に欠いているということでした。

たとえば、この状態の場合:

state = {
    "a" : "A",
    "b" : "B",
}

コードを拡張する場合は、新しい小道具を追加することをお勧めします。そのため、コードの他の場所cで、コンポーネントの状態で値が未定義であるだけでなく、プロパティ自体も未定義である新しいプロパティを作成できます。

これを解決するcには、状態に追加して適切な初期値を指定してください。

例えば、

state = {
    "a" : "A",
    "b" : "B",
    "c" : "C", // added and initialized property!
}

私のエッジケースを説明できたと思います。


0

同じ警告が表示されます:コンポーネントが非表示の非制御入力を制御対象に変更しています。問題を解決できません。何かアイデアはありますか?

export default ({  valueName, onChangeAllg,}) => {

          <TextField
            id={"name"}
            select
            label={"name"}
            value={valueName.geschlecht || ""}
            name={"name"}
            onChange={onChangeAllg}

          >
            {nameList.map((option) => (
              <MenuItem key={option.value} value={option.value}>
                {option.label}
              </MenuItem>
            ))}
          </TextField>

私がしようと試みた({ valueName, valueName: {geschlecht=""}, onChangeAllg,})value={valueName.geschlecht || ""}


見つけた。defaultValue={""}テキストフィールドの内部には、行方不明になった
博士マルタWesterloh

0

警告:コンポーネントは、制御されるタイプのテキストの非制御入力を変更しています。入力要素は、非制御から制御へ(またはその逆)に切り替えないでください。コンポーネントの存続期間中、制御された入力要素と制御されていない入力要素のどちらを使用するかを決定します。

解決策:値が未定義でないかどうかを確認します

React / Formik / Bootstrap / TypeScript

例:

{ values?.purchaseObligation.remainingYear ?
  <Input
   tag={Field}
   name="purchaseObligation.remainingYear"
   type="text"
   component="input"
  /> : null
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.