Home > database >  How to apply styling to a specific item in an array
How to apply styling to a specific item in an array

Time:08-06

I'm trying to make a simple todo in react. I want to be able to click in the button next to the todo text and mark it as complete, with a line passing through it, so I guess the point of the button would be to toggle between the two stylings. But I don't know how to apply the styling to that specific todo. Here's my code so far:

import React, { useState } from 'react';

function App() {
  const [todos, setTodos] = useState([])

  const toggleComplete = (i) => {
    setTodos(todos.map((todo, k) => k === i ? {
      ...todo, complete: !todo.complete
    } : todo))
  }

  const handleSubmit = (event) => {
    event.preventDefault()
    const todo = event.target[0].value

    setTodos((prevTodos) => {
      return [...prevTodos, {
        userTodo: todo, completed: false, id: Math.random().toString()
      }]
    })
  }

  return (
    <div>
      <form onSubmit={handleSubmit}>
        <input placeholder='name'></input>
        <button type='submit'>submit</button>
      </form>

      <ul>
        {todos.map((todos) => <li key={todos.id}>

          <h4>{
          todos.completed ? <s><h4>{todos.userTodo}</h4></s> : <h4>{todos.userTodo}</h4>}
          </h4>

          <button onClick={toggleComplete}>Mark as complete</button>
          
        </li>)}
      </ul>
    </div>
  );
}

export default App;

CodePudding user response:

You can see that the toggleComplete function takes a parameter i which is the id of the todo, so you should call it like onClick={() => toggleComplete(todos.id)}.

However this still didn't work since you are assigning random numbers as strings as id to the todos then iterating on the array.

As Alex pointed out there the bug in your code regarding the completed toggle, so I fixed it and here's a working version of the code you can take a look at and improve:

import React, { useState } from "react";

export default function App() {
  const [todos, setTodos] = useState([]);

  const toggleComplete = (i) => {
    setTodos(
      todos.map((todo, k) => {
        return k === i
          ? {
              ...todo,
              completed: !todo.completed
            }
          : todo;
      })
    );
  };

  const handleSubmit = (event) => {
    event.preventDefault();
    const todo = event.target[0].value;

    setTodos((prevTodos) => {
      return [
        ...prevTodos,
        {
          userTodo: todo,
          completed: false,
          id: prevTodos.length
        }
      ];
    });
  };

  return (
    <div>
      <form onSubmit={handleSubmit}>
        <input placeholder="name"></input>
        <button type="submit">submit</button>
      </form>

      <ul>
        {todos.map((todo) => (
          <li key={todo.id}>
            {todo.completed ? (
              <s>
                <p>{todo.userTodo}</p>
              </s>
            ) : (
              <p>{todo.userTodo}</p>
            )}

            <button onClick={() => toggleComplete(todo.id)}>
              Mark as complete
            </button>
          </li>
        ))}
      </ul>
    </div>
  );
}

CodePudding user response:

There are 2 problems in your code as i see:

  1. typo in the toggleComplete function

Fix: the following code complete: !todo.complete shopuld be completed: !todo.completed as this is the name of the key that you're setting below on handleSubmit.

  1. the toggleComplete function receives as an argument the javascript event object and you are comparing it with the key here: (todo, k) => k === i

(see more here: https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event)

Fix: You can modify the lines of code for the todo render as follows:

        {todos.map((todo, index) => <li key={todo.id}>

            <React.Fragment>{
                todo.completed ? <del><h4>{todo.userTodo}</h4></del> : <h4>{todo.userTodo}</h4>}
            </React.Fragment>

            <button onClick={() => {toggleComplete(index)}}>Mark as complete</button>

        </li>)}
  • Related