【问题标题】:Controlled input changing on setState()setState() 上的受控输入更改
【发布时间】:2019-08-12 20:03:35
【问题描述】:

我在 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
            }
        });
    }

【问题讨论】:

    标签: reactjs


    【解决方案1】:

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

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

    【讨论】:

    • 谢谢。我会在几分钟后打勾。
    • 在这种情况下,您可能希望使用 set state 的函数版本,这样您就不会得到陈旧的值...
    【解决方案2】:

    根据我的经验,通常有两种情况会导致此类警告出现。

    1. 状态属性的初始值未定义,更新时不会更改
    2. 初始值为 '' 正在更改为 null

    【讨论】:

      【解决方案3】:

      试试这个:

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

      分解函数调用:

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

      将函数传递给setState(而不仅仅是一个对象)的好处是,如果你使用传递给函数的状态而不是this.state,当多个setState调用get到时,你将避免一些潜在的错误一起分批....

      【讨论】:

      • 谢谢 Garret,也是不错的选择
      猜你喜欢
      • 2019-11-14
      • 2019-02-22
      • 2020-07-30
      • 2018-01-13
      • 2017-06-30
      • 1970-01-01
      • 1970-01-01
      • 2022-11-28
      • 2023-02-08
      相关资源
      最近更新 更多