React - 更改不受控制的输入

IT技术 javascript node.js reactjs react-state
2021-01-21 16:51:39

我有一个简单的react组件,我认为它具有一个受控输入的形式:

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 正在更改要控制的文本类型的不受控制的输入。输入元素不应从不受控制切换到受控制(反之亦然)。决定在组件的生命周期内使用受控或非受控输入元素

我相信我的输入是受控的,因为它具有value。我想知道我做错了什么?

我正在使用 React 15.1.0

6个回答

我相信我的输入是受控的,因为它具有value。

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

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

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

例如

this.state = { name: '' };

输入将从一开始就受到控制,从而解决了问题。有关更多示例,请参阅React Controlled Components

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

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

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

当 ReactDOM 检查某个字段是否受控制时,它会检查是否value != null(注意它是!=,不是!==),并且由于undefined == null在 JavaScript 中,它决定它是不受控制的。

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

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

感谢您的回答:即使它不是公认的答案,它也比仅仅“指定一个name更好地解释了这个问题
2021-03-14 16:51:39
我已经更新了我的答案以解释受控输入的工作原理。值得注意的是,这里重要的不是undefined最初传递的值相反,它this.state.name不作为状态变量存在的事实使输入不受控制。例如,拥有this.state = { name: undefined };会导致输入被控制。应该理解,重要的是value来自哪里,而不是value是什么。
2021-03-21 16:51:39
对于它的value,同样的事情可能发生在this.props.<whatever>,这就是我的问题。谢谢,亚当!
2021-04-01 16:51:39
是的!如果您传递在 中定义的计算变量render()或标签本身中的表达式(任何计算结果为 ),也会发生这种情况undefined很高兴我能帮上忙!
2021-04-02 16:51:39
@fvgsthis.state = { name: undefined }仍然会导致不受控制的输入。<input value={this.state.name} />脱糖React.createElement('input', {value: this.state.name})因为访问一个对象的不存在的属性返回undefined,这评估为完全相同的函数调用——React.createElement('input', {value: undefined})无论name是未设置还是显式设置为undefined,因此 React 的行为方式相同。您可以在此 JSFiddle 中看到这种行为。
2021-04-09 16:51:39

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

 <input name="name" type="text" value={this.state.name || ''} onChange={this.onFieldChange('name').bind(this)}/>
@JpCrow 很好的答案。您可以在此处阅读有关此内容的更多信息stackoverflow.com/a/476445/3850405 developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
2021-03-14 16:51:39
<input name="name" type="text" defaultValue="" onChange={this.onFieldChange('name').bind(this)}/> 我认为这也行
2021-03-16 16:51:39
非常感谢,这正是我正在寻找的。我应该记住使用这种模式有什么缺点或潜在问题吗?
2021-03-19 16:51:39
这对我有用,因为字段是从 API 动态呈现的,所以在安装组件时我不知道字段的名称。这很有用!
2021-03-31 16:51:39

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

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

例子:

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

当您使用复选框时,您可能需要checked使用!!.

例子:

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

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

这对我有用,谢谢,是的,我 100% 同意这一点,初始状态是 {},因此检查值将是未定义的并使其不受控制,
2021-03-15 16:51:39
双爆炸解决方案工作得很好,谢谢!
2021-04-01 16:51:39
这对我有帮助。谢谢你。
2021-04-12 16:51:39

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

<input name='myInput' value={this.state.myInput || ''} onChange={this.handleChange} />
荣幸 :)
2021-03-19 16:51:39