简体   繁体   中英

Why am I getting an error here? React Todo list

I am trying to create a todo list using React but i cant seem to understand why I am getting the error: "Warning: Cannot update during an existing state transition (such as within render ). Render methods should be a pure function of props and state."

Here's the code:

import React from 'react'
import ReactDOM from 'react-dom'

class Todo extends React.Component{
  constructor(props){
    super(props)
    this.state = {
      input: '',
      list: []
    }
    this.handleChange = this.handleChange.bind(this)
    this.reset = this.reset.bind(this)
    this.removeItem = this.removeItem.bind(this)
    this.add = this.add.bind(this)
  }
  add(){ //Adds a new task
    
    const newItem = {
      value: this.state.input,
      id: Math.random + Math.random
    };
    const listed = [...this.state.list]
    listed.push(newItem)
    this.setState({
      input: '',
      list: listed
    })
  }
  removeItem(id){ //deletes a task
    const list = [...this.state.list]
    const updatedList = list.filter(obj => {
      return obj.id !== id
    })
    this.setState({
      list: updatedList
    })
  }
  handleChange(e){
    this.setState({input: e.target.value})
  }
  reset(e){
    e.preventDefault()
  }
  render(){
    return (
      <div>
        <form action="" onSubmit={this.reset}>
          <input type="text" value={this.state.input} placeholder='Enter a task..' onChange={this.handleChange}  />
          <button onClick={this.add}>Add Task</button>
        {this.state.list.map(item => {   //updates when a task is added or removed
          return (
            <div key={item.id}>
            <h1>{item.value}</h1>
            <button onClick={this.removeItem(item.id)}>X</button>
            </div>
          )
        })}
        </form>
      </div>
    )
  }
}

ReactDOM.render(<Todo />,document.getElementById('root'))

Because you are calling removeItem on render. It needs to be wrapped in a separate function:

 <button onClick={() => this.removeItem(item.id)}>X</button>

So that you only call it onClick and not on render.

  1. <button onClick={this.removeItem(item.id)}>X</button> In this button the event handler you have provided runs immediately due to the presents of the () at the end. To prevent this and still provide your argument item.id you can enclose the handler this.removeItem(item.id) with in another function. I like the arrow function for this so mine looks like this <button onClick={ ()=>this.removeItem(item.id) }>X</button> .

  2. Math.random + Math.random is not returning a number like you would want for the element key. This is because your have neglected to include () at telling JS to run the function and return an int.

After making these changes, I ran it in codepen.io and it seemed to work fine.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM