React.js 使用非状态变量获取错误作为组件正在更改要控制的文本类型的不受控制的输入

Posted

技术标签:

【中文标题】React.js 使用非状态变量获取错误作为组件正在更改要控制的文本类型的不受控制的输入【英文标题】:React.js when using non state variable Getting error as A component is changing an uncontrolled input of type text to be controlled 【发布时间】:2019-04-21 12:35:07 【问题描述】:

我正在尝试使用非状态变量 'newItem' 来保存输入值

import React,  Component  from 'react';

class List extends Component 
  constructor() 
    super();
    this.state =  items: [1, 2] ;
    this.newItem = undefined;
  
  changeNewItem = e => 
    this.newItem = e.target.value;
    console.log(this.newItem);
  ;
  addItem = e => 
    if (e.keyCode !== 13) return;
    var tmp_list = this.state.items;
    tmp_list.push(this.newItem);
    this.setState( items: tmp_list , () => 
      this.newItem = '';
    );
  ;
  render() 
    return (
      <div>
        <ul>
          this.state.items.map(item => (
            <li key=item>item</li>
          ))
        </ul>
        <input
          type="text"
          placeholder="add item"
          value=this.newItem
          onChange=this.changeNewItem
          onKeyUp=this.addItem
        />
      </div>
    );
  


export default List;

当我在文本框中按回车键时,项目被添加到数组中,但出现如下错误

index.js:1452 警告:组件正在更改要控制的文本类型的不受控制的输入。输入元素不应从不受控切换到受控(反之亦然)。决定在组件的生命周期内使用受控输入元素还是不受控输入元素。更多信息: 在输入中(在 List.js:29) 在 div 中(在 List.js:23 处) 在列表中(在 App.js:9 处) 在应用程序中(在 src/index.js:8)

【问题讨论】:

我的情况不同,更新问题 【参考方案1】:

您的问题是输入元素的初始值未定义,然后您使用变量this.newItem 控制它。因此,您会收到试图将不受控制的输入更改为受控的警告。

将值初始化为 empty string 而不是 undefined。此外,如果您希望输入组件更改值,请使用状态而不是类变量

import React,  Component  from 'react';

class List extends Component 
  constructor() 
    super();
    this.state =  items: [1, 2], newItem: '' ;
  
  changeNewItem = e => 
    this.setState(newItem: e.target.value)
  ;
  addItem = e => 
    if (e.keyCode !== 13) return;
    var tmp_list = this.state.items;
    tmp_list.push(this.state.newItem);
    this.setState( items: tmp_list , () => 
      this.state.newItem = '';
    );
  ;
  render() 
    return (
      <div>
        <ul>
          this.state.items.map(item => (
            <li key=item>item</li>
          ))
        </ul>
        <input
          type="text"
          placeholder="add item"
          value=this.state.newItem
          onChange=this.changeNewItem
          onKeyUp=this.addItem
        />
      </div>
    );
  


export default List;

【讨论】:

我试图理解,我们可以在不将 newItem 变量移动到 state 的情况下解决这个问题吗? 您可以使用不受控制的输入并摆脱 onChange 事件。您可以使用 ref 读取输入值【参考方案2】:

更改为不受控制的输入并使用React.createRef(),由Comment建议

import React,  Component  from 'react';

class List extends Component 
  newItem;
  constructor() 
    super();
    this.state =  items: [1, 2] ;
    this.input = React.createRef();
  
  changeNewItem = e => 
    this.newItem = e.target.value;
    console.log(this.newItem);
  ;
  addItem = e => 
    if (e.keyCode !== 13 || !this.newItem) return;
    var new_list = this.state.items.concat(this.newItem);
    this.setState( items: new_list , () => 
      this.newItem = '';
      this.input.current.value = '';
    );
  ;
  render() 
    return (
      <div>
        <ul>
          this.state.items.map(item => (
            <li key=item>item</li>
          ))
        </ul>
        <input
          type="text"
          placeholder="add item"
          ref=this.input
          onChange=this.changeNewItem
          onKeyUp=this.addItem
        />
      </div>
    );
  


export default List;

【讨论】:

以上是关于React.js 使用非状态变量获取错误作为组件正在更改要控制的文本类型的不受控制的输入的主要内容,如果未能解决你的问题,请参考以下文章

在 React.js 中实现无状态子组件

react.js 时钟组件

React JS变量和文本字段未更新

如何将从 API 获取的数据作为道具传递给其路由在 React JS 的另一个页面中定义的组件?

如何在 react.js 中跨子组件持久化数据或状态?

React Js - Flux 中的状态管理