Trying to set state for individual todo items and have them maintain and toggle between 3 colors on click

They also must maintain their color after items are deleted (and thus re-arranged). Currently, everything works except nothing happens when I click on each item.

I've spent over 20 hrs trying to get this to work and the closest I've come is to having it work perfectly other than after I delete an item the item below the deleted item takes on the color of the deleted item. I have changed my code up quite a bit since then, but at this point I'm completely baffled as to why it isn't updating the color. For some reason, it isn't making it past the first conditional in my handleClick(), even though the conditional is true (as far as I can tell).

This is really bothering me and at this point becoming a hindrance to my progress because it's so distracting. please help!

I signed up to stackOverflow just for this question (and perhaps the first of many).

Here is all the code that should be required to understand what I'm doing wrong. I can provide a github link to my repo if anyone requests it.

import React, { Component } from 'react'
import './App.css'
import Header from './components/layout/Header'

class App extends Component {
  state = {
    todos: [
      {
        id: 1,
        title: 'click me',
        status: 'red',
      },
    ],
    input: '',
    counter: 2,
  }

  onChange = (event) => {
    this.setState({ input: event.target.value })
  }

  onSubmit = (event) => {
    event.preventDefault()
    this.setState({
      todos: [
        ...this.state.todos,
        {
          title: this.state.input,
          id: this.state.counter,
          status: 'red',
        },
      ],
      input: '',
      counter: this.state.counter + 1,
    })
  }

  removeItem = (id) => {
    this.setState({
      todos: [...this.state.todos.filter((x, i) => i !== id)],
    })
  }

  handleClick = (e) => {
    this.setState({
      todos: this.state.todos.map((todo) => {
        if (todo.status === 'red' && todo.id === e.currentTarget.value) {
          todo.status = 'yellow'
        } else if (
          todo.status === 'yellow' &&
          todo.id === e.currentTarget.value
        ) {
          todo.status = 'green'
        } else if (
          todo.status === 'green' &&
          todo.id === e.currentTarget.value
        ) {
          todo.status = 'red'
        }
        return todo
      }),
    })
  }

  render() {
    return (
      <div className="App">
        <Header />
        <form style={{ display: 'flex' }} onSubmit={this.onSubmit}>
          <input
            type="text"
            name="title"
            style={{ flex: '10', padding: '5px' }}
            placeholder="Add Todo ..."
            value={this.state.input}
            onChange={this.onChange}
          />
          <input
            type="submit"
            value="Submit"
            className="btn"
            style={{ flex: '1' }}
          />
        </form>

        <ul>
          {this.state.todos.map((todo, idx) => {
            return (
              <li key={todo.id}>
                <span
                  onClick={(e) => this.handleClick(e)}
                  style={{ color: todo.status }}
                  value={todo.id}
                  id={idx}
                >
                  {todo.title}
                </span>
                <span>
                  <button onClick={() => this.removeItem(idx)}>X</button>
                </span>
              </li>
            )
          })}
        </ul>
      </div>
    )
  }
}

export default App


Read more here: https://stackoverflow.com/questions/64370928/trying-to-set-state-for-individual-todo-items-and-have-them-maintain-and-toggle

Content Attribution

This content was originally published by Michael Scoggins at Recent Questions - Stack Overflow, and is syndicated here via their RSS feed. You can read the original post over there.

%d bloggers like this: