在setState()

时间:2019-03-21 21:16:13

标签: reactjs

我在React组件中有这个构造函数:

constructor() {

        super();

        this.state = {
            info: {
                title: '',
                description: '',
                height: ''
            }
        }

...

还有一个状态由输入控制的表单:

    <form onSubmit={this.handleFormSubmit}>
      <label>Title:</label>
      <input type="text" name="title" value={this.state.info.title} onChange={(e) => this.handleChange(e)} />
      <label>Description:</label>
      <input type="text" name="description" value={this.state.info.description} onChange={(e) => this.handleChange(e)} />
...

当我在表单上键入任何内容时,我想我的处理程序有问题,因为我得到警告“ 警告:组件正在将文本类型的受控输入更改为不受控制。输入元素不应切换从受控变为非受控(反之亦然)。决定在组件的使用寿命中使用受控或非受控输入元素。

检查控制台,似乎状态正在更新正在键入的每个属性值,并删除其他属性,而应该保留所有这些属性,而仅更新更改的属性。

这是我的处理程序:

handleChange(event) {
        let { name, value } = event.target;
        this.setState({
            info: {
                [name]: value
            }
        });
    }

3 个答案:

答案 0 :(得分:3)

您正在使用的一个仅更新一个道具,而其他被剥离的导致React的警告显示。您可以使用传播来保持其他人

handleChange(event) {
    let { name, value } = event.target;
    this.setState({
        info: {
            ...this.state.info,
            [name]: value
        }
    });
}

答案 1 :(得分:1)

通常有2种情况会在我的经历中引起这种警告。

  1. 处于状态的属性的初始值未定义,并且在更新时不会更改
  2. 初始值为”,并将其更改为null

答案 2 :(得分:1)

尝试一下:

handleChange(event) {
        let { name, value } = event.target;
        this.setState(({info}) =>({
            info: {
                [name]: value
            }
        }));
    }

中断函数调用:

  • 首先您有this.setState(updaterFunction)updaterFunctionsetState调用,并以先前的状态作为参数,并且该函数应返回一个带有要更新的状态键的对象(它与先前的状态浅合并)。 / li>
  • 因为setState只是 shallow 合并(无论您传递的是对象还是函数),如果您有一个像this.state.foo.bar一样的对象,并且您进行更新状态为{foo: {bar: 'qux'} }之类的对象,旧的foo将不会与新的foo合并,而是会被替换。因此,您的更新程序功能需要手动进行更深层次的合并。
  • updaterFunction看起来像这样({info})=>({…})。我们将info从先前的状态中拉出,然后返回一个对象,并使用info手动进行更深的合并。

将函数传递给setState(而不仅仅是对象)的好处是,如果您使用传递给函数的状态而不是this.state,则当多个{ {1}}个呼叫被汇总在一起。...