首页 > 解决方案 > 从没有 setState 的输入更新对象

问题描述

我是 React JS(和 JS,一般来说)的新手。现在我正在尝试编写一个简单的任务跟踪器。

所以,我在MyTodoList类的状态元素中有所有任务。在那里,我使用Task常量分别绘制每个任务。

我想用 2 个输入实现添加一个新任务:名称和描述。

我在MyTodoList中创建一个新对象(newTask),以便稍后将其添加到状态列表中。但是,我想我正在为输入错误编写 onChange 方法。newTask 似乎正在函数内部更新(将其记录在控制台中),但它在外部没有改变(在输入空间中,输入没有变化)。显然我不能使用 setState 因为我想更新一个非状态对象(对象是可变的,所以我不明白为什么它不会改变)。

我不确定我是否错误地更新了对象,或者我添加新任务的整个概念是否错误。如果您能解释我的错误,将不胜感激。

这是代码:

const TaskAdd = ({value, onChange, placeholder, name}) => {
  return (
      <input value={value} onChange={onChange} placeholder={placeholder} name={name}/>
  )
}


const Task = ({id, name,  description, completed}) => {
    const handleClick = () => {
    }
  
    return (
      <div className='task'>
        <h3>{name}</h3>
        <div>{description}</div>
        <div>{completed}</div>
        <button onClick={handleClick} className='button1'>CLICK</button>
      </div>
    )
  }


class MyTodoList extends React.Component {
  state = {
    tasks: [
      {
        id: 1,
        name: 'Walk the dog',
        description: 'Have to walk the dog today',
        completed: false,
      },

    ]
  }

  maxId = this.state.tasks[this.state.tasks.length - 1].id;

  newTask = {
    id: this.maxId,
    name: '',
    description: '',
    completed: false,
  }

  handleChange = (event) => {
    const {value, name} = event.currentTarget

    this.newTask[name] = this.newTask[name] + value
  }

  render () {
    return(
      <div>
        <header><h1>TO-DO</h1></header>
        <div className='addTask'>
          <h2>Let's add something new</h2>

          <TaskAdd value={this.newTask.name} onChange={this.handleChange} 
          placeholder='Name' name='name'/>

          <TaskAdd value={this.newTask.description} onChange={this.handleChange} 
          placeholder='Description' name='description'/>
          <p> {this.newTask.name}</p>

          <button className='button1'><h3>Add</h3></button>
        </div>
        <div>{this.state.tasks.map(task => <Task id={task.id} name={task.name} 
        description={task.description} completed={task.completed}/>)}
        </div>

      </div>
      )
  }

}

const App = () => {
  return (
    <MyTodoList />
  )
}

export default App;

标签: reactjsobjectinput

解决方案


显然我不能使用 setState 因为我想更新一个非状态对象

如果要更新屏幕,则必须使用 state。setState 函数是告诉 react 某些东西发生了变化并且需要重新渲染的唯一方法。

因此,扩展您的状态以在其中包含新任务:

  state = {
    tasks: [
      {
        id: 1,
        name: 'Walk the dog',
        description: 'Have to walk the dog today',
        completed: false,
      },

    ]
    newTask: {
      id: 2,
      name: '',
      description: '',
      completed: false,
    }
  }

有了它,您需要更新您的渲染函数以在状态下访问它,如下所示:

<TaskAdd 
  value={this.state.newTask.name} 
  onChange={this.handleChange} 
  placeholder='Name'
  name='name'
/>

然后当你设置状态时,制作一个副本而不是变异:

handleChange = (event) => {
  const {value, name} = event.currentTarget

  this.setState({
    newTask: {
      ...this.state.newTask,
      [name]: this.state.newTask[name] + value
    }
  });
}

您的代码没有包含 add 按钮的实现,但是当您这样做时,您可能会使用 this.state.newTask 并将其添加到 this.state.tasks 的末尾(您将制作数组的副本,而不是改变它),然后创建一个新对象来替换 this.state.newTask


*好的,从技术上讲,有 forceUpdate,但不要使用它。


推荐阅读