使用带有obj的数组的索引来删除项目或更改obj中的标志

时间:2018-07-30 16:36:45

标签: javascript arrays reactjs object

我是react和javascript领域的新手,我正尝试创建一个todo应用程序来学习,到目前为止,除2件事(删除和if完成功能)外,其他所有功能都可以正常工作。我要实现的目标是使onClick按钮将完成的状态从false更改为true,然后将直通传递给特定的待办事项。之后,我将有3个不同的计数器来显示待办事项的总数,已完成和未完成的数量。代码如下:

class App extends Component {
 constructor() {
 super();
  this.state = {
    text: '',
    notes: [
      {todo: "test", completed: true},
      {todo: "test2", completed: false}
    ]
  }
}

handleChange = (e) => {
  this.setState({ text: e.target.value })
}

handleSubmit = (e) => {
  e.preventDefault();
  if(!this.state.text.length) { return }
  const newTodo = {
    todo: this.state.text,
    completed: false
  }
  const notes = this.state.notes
  notes.push(newTodo)
  this.setState({
    text: '',
    notes: notes
  })
}

handleClick = (index) => {
  const notes = this.state.notes
  notes[index].completed = !notes[index].completed
  this.setState({ notes })
}

handleDelete = (index) => {
  const notes = this.state.notes
  notes.splice(index, 1)
  this.setState({ notes })
}

render() {
  let notes = this.state.notes.map((todo, index) => {
    return <Todo key={index} note={todo} 
    deleteTodo={this.handleDelete} handleClick={this.handleClick}/>
  });
 return (
   <div className="App">
     <div className="notes-wrapper">
     <Header />
     <Form 
       handleSubmit={this.handleSubmit}
       handleChange={this.handleChange}
       text={this.state.text}
     />
     {notes}
     <Footer notesLength={this.state.notes.length} />
     </div>
   </div>
  );
 }
}

如果我将obj的数组更改为一个简单的数组,例如array = [1,2,3],则可以执行array.splice(index,1)并运行良好,但是在这种情况下,索引存在问题我明白。删除功能正在工作,但正在删除错误的元素,而不是单击的元素,并且如果我这样做notes [1] .completed =!notes [1] .completed也正在工作,但在两个按钮上都起作用,它将仅更改第一个按钮项目。我不知道对于初学者来说是否很复杂。谢谢!

const Todo = (props) => {
  return (
    <div className="todo-wrapper">
        <li style={{textDecoration: props.note.completed ? 
        'line-through' : 'none'}}>
            <button className="btn btn-remove" 
             onClick={props.deleteTodo}>Remove</button>
             {props.note.todo}
            <button className="btn btn-status" 
            onClick={props.handleClick}>{props.note.completed ? 
           "Undo" : "Done"}</button>
        </li>
    </div>
  );

1 个答案:

答案 0 :(得分:2)

您需要注意两件事,

首先:您没有将索引传递给Todo组件的handleDelete和handleClick函数。

第二:您不应更改原始状态。就像对待它一成不变一样

handleClick = (index) => {
  const notes = [...this.state.notes]  // create a copy
  notes[index].completed = !notes[index].completed
  this.setState({ notes })
}

handleDelete = (index) => {

  this.setState(prevState => ({ notes: [...prevState.notes.slice(0, index), ...prevState.notes.slice(index) }))
}

render() {
  let notes = this.state.notes.map((todo, index) => {
    return <Todo key={index} note={todo} index={index}
    deleteTodo={this.handleDelete} handleClick={this.handleClick}/>
  });
 return (
   <div className="App">
     <div className="notes-wrapper">
     <Header />
     <Form 
       handleSubmit={this.handleSubmit}
       handleChange={this.handleChange}
       text={this.state.text}
     />
     {notes}
     <Footer notesLength={this.state.notes.length} />
     </div>
   </div>
  );
 }

您的Todo组件将具有

<button className="btn btn-remove" onClick={() => props.deleteTodo(props.index)}>Remove</button>

类似

<button className="btn btn-status" onClick={() => props.handleClick(props.index)}>{props.note.completed ? "Undo" : "Done" }</button>