2

I just wonder something about updating state in React. I'm working on basic "to-do app". I created a list & mapped for each element. The user can add a new element in the list and can change the status of the element.

Now, I want the state to update for every click. For example, when the user clicked the completed button, the state is called list will be contained only completed items. I can do it. But after I update the list, I can't access default list. For example, when the user click the button;

changeView(event) {
let clickStatus = event.target.value
if (clickStatus = 'completed') {
const newList = this.state.list.filter((item) => {
return item.completed
})
this.setState({
this.state.list: newList
})
}

But after this, I can't access the list that contains every item.

This is my code:

class App extends React.Component{
  constructor(props) {
    super(props)
    this.state = {
      list: [
        {
          'text': 'First Item',
          'completed': false
        },
        {
          'text': 'Second Item',
          'completed': false
        },
        {
          'text': 'Third Item',
          'completed': true
        }
      ]
    }
    this.handleStatus = this.handleStatus.bind(this)
    this.handleSubmit = this.handleSubmit.bind(this)
  }

  handleSubmit(event) {
    event.preventDefault()
    const newItem = {
      'text': this.refs.new.value,
      'completed': false
    }
    this.setState({
      list: this.state.list.concat([newItem])
    })
    this.refs.new.value = ''
  }

  handleStatus(event) {
    const itemText = this.state.list[event.target.value].text
    const itemStatus = this.state.list[event.target.value].completed
    const newItem = {
      'text': itemText,
      'completed': itemStatus ? false : true
    }
    const list = this.state.list
    list[event.target.value] = newItem
    this.setState({
      list
    })
  }

  render() {

    const Item = this.state.list.map((item, index) => {
      return <li onClick={this.handleStatus} className={(item.completed) ? 'done' : 'default'} value={index} status={item.completed}>{item.text}</li>
    })

    return (
      <div>
        <form onSubmit={this.handleSubmit}>
          <input type='text' ref='new'></input>
          <button type='submit'>Add</button>
        </form>
        <ul>
          {Item}
        </ul>
        <div>
          <button
            value='all'
            type='submit'>All
          </button>
          <button
            value='completed'
            type='submit'>Completed
          </button>
          <button
            value='pending'
            type='submit'>Pending
          </button>
        </div>
      </div>
    )
  }
}

ReactDOM.render(<App/>, document.getElementById('app'))

1 Answer 1

3

Instead of updating items list in state on each filter change use state property to decide which items should be displayed during rendering.
State should always store whole list and you should just set state property indicating that completed filter is active:

changeView(event) {
    let clickStatus = event.target.value
    this.setState({
        completedFilter: clickStatus === 'completed' ? true : false
    })
}

and then use this property to filter displayed items in render method:

render() {
    let fileredItems = this.state.list;
    if (this.state.completedFilter) {
        fileredItems = this.state.list.filter((item) => item.completed);
    }
    return (
        ...
        {
            filteredItems.map((item) => {
                //return item node
            })
        }
    );

}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.