反应 - 改变不受控制的输入

ale*_*333 308 javascript node.js reactjs react-state

我有一个简单的反应组件,我相信有一个受控输入的形式:

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;
Run Code Online (Sandbox Code Playgroud)

当我运行我的应用程序时,我收到以下警告:

警告:MyForm正在更改要控制的类型文本的不受控制的输入.输入元素不应从不受控制切换到受控制(或反之亦然).决定在组件的使用寿命期间使用受控或不受控制的输入元素

我相信我的输入是有控制的,因为它有一个值.我想知道我做错了什么?

我正在使用React 15.1.0

fvg*_*vgs 451

我相信我的输入是有控制的,因为它有一个值.

对于要控制的输入,其值必须与状态变量的值相对应.

在您的示例中最初未满足该条件,因为this.state.name最初未设置.因此,输入最初是不受控制的.一旦onChange处理程序第一次被触发,this.state.name就会被设置.此时,满足上述条件并且认为输入受到控制.从不受控制到受控制的过渡产生了上面看到的错误.

通过this.state.name在构造函数中初始化:

例如

this.state = { name: '' };
Run Code Online (Sandbox Code Playgroud)

输入将从一开始就被控制,解决问题.有关更多示例,请参阅React Controlled Components.

与此错误无关,您应该只有一个默认导出.你上面的代码有两个.

  • 这个答案略有不正确.如果`value` prop具有非null /未定义的值,则输入被控制*.prop不需要对应于状态变量(它可以只是一个常量,并且该组件仍然被认为是受控的).亚当的答案更正确,应该被接受. (11认同)
  • 很难多次阅读答案并遵循想法,但是此答案是讲述故事并让观众同时理解的理想方式。回答级上帝! (5认同)
  • 如果循环中有动态字段怎么办?例如,您将字段名称设置为`name = {'question_groups。$ {questionItem.id}'}`?? (2认同)
  • 动态字段如何工作。正在动态生成表单,然后在状态内部的对象中设置字段名称,我是否仍然必须先手动设置状态中的字段名称,然后将它们传输到我的对象? (2认同)
  • 是的-从技术上来说这是错误的答案(但有帮助)。关于这一点的注意事项-如果您正在处理单选按钮(其“值”的控制方式有所不同),则即使您的组件已被控制(当前),该反应警告实际上也会引发。https://github.com/facebook/react/issues/6779,可以通过添加!!来解决 对isChecked的真实性 (2认同)

Lei*_*cki 107

当你第一次渲染你的组件时,this.state.name没有设置,所以它评估为undefined,你最终传递value={undefined}给你的input.

当ReactDOM检查字段是否被控制时,它会检查是否value != null(注意它是!=,而不是!==),并且因为undefined == null在JavaScript中,它决定它是不受控制的.

因此,当onFieldChange()调用时,this.state.name设置为字符串值,您的输入将从不受控制变为受控制.

如果你this.state = {name: ''}在构造函数中执行,因为'' != null,您的输入将始终具有值,并且该消息将消失.

  • 对于它的价值,同样的事情可能发生在`this.props.<whatever>`,这就是我的问题.谢谢,亚当! (5认同)
  • 感谢您的回答:尽管它不是被接受的答案,但它比仅仅“指定一个‘名称’”更好地解释了这个问题。 (3认同)
  • @fvgs 具有 `this.state = { name: undefined }` 仍然会导致不受控制的输入。`&lt;input value={this.state.name} /&gt;` 脱糖为 `React.createElement('input', {value: this.state.name})`。因为访问对象不存在的属性会返回“undefined”,所以其计算结果为完全相同的函数调用——“React.createElement('input', {value: undefined})”——无论“name”是否未设置或显式设置为“未定义”,因此 React 的行为方式相同。[您可以在此 JSFiddle 中看到此行为。](https://jsfiddle.net/adambrenecki/7y3nmxcd/1/) (2认同)

JpC*_*row 43

另一种方法是在输入中设置默认值,如下所示:

 <input name="name" type="text" value={this.state.name || ''} onChange={this.onFieldChange('name').bind(this)}/>
Run Code Online (Sandbox Code Playgroud)


Shu*_*man 16

我有同样的问题。问题是当我将状态信息保留为空白时

  const [name, setName] = useState()
Run Code Online (Sandbox Code Playgroud)

我通过添加这样的空字符串来修复它

  const [name, setName] = useState('')
Run Code Online (Sandbox Code Playgroud)

  • 谢谢你,先生!这是我的问题并解决 (5认同)

Muh*_*nan 11

我知道其他人已经回答了这个问题.但是,这里一个非常重要的因素可能会帮助其他人遇到类似的问题:

您必须onChange在输入字段中添加处理程序(例如textField,checkbox,radio等).并始终通过onChange处理程序处理活动,如:

<input ... onChange={ this.myChangeHandler} ... />
Run Code Online (Sandbox Code Playgroud)

当你使用复选框时,你可能需要处理它的checked状态,!!如:

<input type="checkbox" checked={!!this.state.someValue} onChange={.....} >
Run Code Online (Sandbox Code Playgroud)

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


Gre*_*lor 7

在构造函数中将字段值设置为“”(空字符串)的一个潜在弊端是,如果该字段是可选字段并且未编辑。除非您在发布表单之前进行一些按摩,否则该字段将作为空字符串而不是NULL保留在数据存储中。

此替代方法将避免使用空字符串:

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

... 

<input name="name" type="text" value={this.state.name || ''}/>
Run Code Online (Sandbox Code Playgroud)


KAR*_*N.A 7

当您onChange={this.onFieldChange('name').bind(this)}在输入中使用时,您必须将状态空字符串声明为属性字段的值。

不正确的方法:

this.state ={
       fields: {},
       errors: {},
       disabled : false
    }
Run Code Online (Sandbox Code Playgroud)

正确方法:

this.state ={
       fields: {
         name:'',
         email: '',
         message: ''
       },
       errors: {},
       disabled : false
    }
Run Code Online (Sandbox Code Playgroud)


MUS*_*SSI 7

解决此问题的简单方法是默认设置一个空值:

<input name='myInput' value={this.state.myInput || ''} onChange={this.handleChange} />
Run Code Online (Sandbox Code Playgroud)


Emp*_*ser 5

如果组件上的 props 作为状态传递,请为输入标签设置默认值

<input type="text" placeholder={object.property} value={object.property ? object.property : ""}>
Run Code Online (Sandbox Code Playgroud)


lak*_*ith 5

在初始状态下将值设置为 'name' 属性。


Men*_*ris 5

就我而言,我确实缺少了一些琐碎的东西。

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

收到警告时,我的状态如下:

state = {
   myObject: undefined
}
Run Code Online (Sandbox Code Playgroud)

通过更改状态以引用我的值的输入,我的问题得以解决:

state = {
   myObject: {
      inputValue: ''
   }
}
Run Code Online (Sandbox Code Playgroud)

  • 感谢您帮助我了解我遇到的真正问题 (2认同)

小智 5

对此的更新。对于 React Hooks 使用const [name, setName] = useState(" ")


Rob*_*ohr 5

如果 this.state.name 为 null,则只需创建一个后备到 '' 。

<input name="name" type="text" value={this.state.name || ''} onChange={this.onFieldChange('name').bind(this)}/>
Run Code Online (Sandbox Code Playgroud)

这也适用于 useState 变量。