Пытаетесь обновить объект в состоянии, но ошибка не позволяет мне это сделать?

У меня есть список дел. Я пытаюсь реализовать функцию, при которой при наведении курсора на задачу (элемент li) появляется кнопка «Удалить». Однако единственный способ, которым я могу заставить его работать, - это обновить основное состояние, добавив состояние «Hover: false» и обновив его таким образом, но это заставляет ВСЕ кнопки удаления появляться при наведении.

Я хочу, например, навести курсор на вторую задачу, и появится только кнопка удаления этой задачи, а остальные останутся скрытыми. Как мне реализовать это в моей функции?

Вот мой код до сих пор

  import React from "react";
  import { isTemplateElement, tsStringKeyword } from "@babel/types";

  class TodoListt extends React.Component {
    state = {
      userInput: '',
      todos: [],
      editMode: false,
      hover: false
    }

    hoverOn = (index) => {
      const todos = [...this.state.todos];
      const updatedTodos = todos.map((todo, todoIndex) => {
        if (index == todoIndex) {
          return {
            ...todos,
            hover: true
          };
        } else {
          return todo;
        }
      })
      this.setState({
        todos: updatedTodos
      })
    }

    hoverOff = () => {
      console.info("Not Hovering");
    }

    handleChangeEvent(e, index) {
      this.setState({
        userInput: (e)
      })
      console.info(this.state.userInput)
    }


    handleSubmit(e, index) {
      e.preventDefault();
      const { todos, userInput } = this.state;
      this.setState({
        todos: [...todos, {
          text: userInput,
          key: Date.now(),
          editMode: false,
          hover: false
        }],
        userInput: ''
      }
      )
    }

    handleDelete(index) {
      const todos = [...this.state.todos];
      todos.splice(index, 1);
      this.setState({
        todos
      })
    }

    handleEdit(index) {
      const todos = [...this.state.todos];
      const updatedTodos = todos.map((todo, todoIndex) => {
        if (index == todoIndex) {
          return {
            ...todos,
            editMode: true
          };
        } else {
          return todo;
        }
      });
      this.setState(
        {
          ...this.state,
          todos: updatedTodos
        },
        () => console.info(this.state)
      );

    }

    handleUpdateChange = (e, index) => {
      const todos = [...this.state.todos];
      const updatedTodos = todos.map((todo, todoIndex) => {
        if (index == todoIndex) {
          return {
            ...todo,
            text: e.target.value
          };
        } else {
          return todo;
        }
      });
      this.setState({
        ...this.state,
        todos: updatedTodos
      });
    };



    render() {
      return (

        < div className = "test">
          <form onSubmit = {(e) => this.handleSubmit(e)}>
            <input
              type = "text"
              class = "form-control mb-2"
              placeholder = "enter a todo..."
              onChange = {(e) => this.handleChangeEvent(e.target.value)}
              value = {this.state.userInput}
            />
            <button type = "submit" class = "btn btn-primary">Submit</button>
          </form>

          <ul class = "list-group">

            {this.state.todos.map((todos, index) => (

              this.state.editMode[index] ?
                <div>
                  <input type = "text" defaultValue = {todos.text} />
                </div>
                :


                <li
                  key = {todos.key}
                  className = "list-group-item w-100"
                  onMouseEnter = {(index) => this.hoverOn(index)}
                  onMouseLeave = {(index) => this.hoverOff(index)}
                  onDoubleClick = {(index) => this.handleEdit(index)}>
                  {todos.text}
                  <div class = "delButton">
                    <button className = {todos.hover ? "visable" : "notVisable"} onClick = {(index) => this.handleDelete(index)}>Remove</button>
                  </div>
                </li>
            )
            )
            }

          </ul>
        </div>
      )
    }
  }
  export default TodoListt;

Я бы попробовал выделить li как отдельный компонент и инкапсулировать в него вашу логику, чтобы у каждой задачи было свое состояние.

brbcoding 21.05.2019 01:02

Эй, Донни! Только что написал вам еще один ответ, вытекающий из вашего вчерашнего вопроса о доступе к реквизиту в массиве. Дайте знать, если у вас появятся вопросы. Я разбил код на части, чтобы у вас был отдельный компонент Todo для каждого элемента :)

Chris Ngo 21.05.2019 02:01
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
2
61
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Вы можете легко создать это поведение с помощью css. Дайте вашему элементу списка и вашей кнопке имя класса, а затем вот так:

.myButton {
     display: none;
 }

 .myListItem:hover > .myButton {
     display: block;
  }

Независимо от того, отображается ли кнопка, должно быть состояние. Это состояние не связано напрямую с TodoList, а скорее с каждым элементом в списке, было бы разумно сделать каждый li своим собственным компонентом Stateful React. Тогда каждый компонент мог бы отслеживать свое собственное состояние наведения.

Вам следует подумать о рефакторинге кода в TodoList, чтобы вы могли отображать отдельный компонент Todo для каждого добавленного элемента.

Таким образом, компонент Todo имеет собственную часть состояния для управления, что упрощает создание на его основе дополнительных функций.

Я работаю над кодом, который предоставил вам вчера, но вот, по сути, то, что вам нужно для этого.

Вот песочница для справки: https://codesandbox.io/s/1n1c9

Список дел

import React from "react";
import Todo from "./Todo";

class TodoListt extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      userInput: "",
      todos: [],
      editMode: false
    };

    this.handleChangeEvent = this.handleChangeEvent.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
    this.handleDelete = this.handleDelete.bind(this);
    this.handleEdit = this.handleEdit.bind(this);
    this.handleUpdateChange = this.handleUpdateChange.bind(this);
    this.handleUpdateSubmit = this.handleUpdateSubmit.bind(this);
  }
  handleChangeEvent(e, index) {
    this.setState({
      userInput: e
    });
  }

  handleSubmit(e, index) {
    e.preventDefault();
    const { todos, userInput } = this.state;
    this.setState(
      {
        todos: [
          ...todos,
          {
            text: userInput,
            key: Date.now(),
            editMode: false
          }
        ],
        userInput: ""
      },
      () => console.info(this.state)
    );
  }

  handleDelete(index) {
    const todos = [...this.state.todos];
    console.info(index);
    todos.splice(index, 1);
    this.setState({
      todos
    });
  }

  handleEdit(index) {
    const todos = [...this.state.todos];
    const updatedTodos = todos.map((todo, todoIndex) => {
      if (index == todoIndex) {
        return {
          ...todo,
          editMode: true
        };
      } else {
        return todo;
      }
    });
    this.setState(
      {
        ...this.state,
        todos: updatedTodos
      },
      () => console.info(this.state)
    );
  }

  handleUpdateChange = (e, index) => {
    const todos = [...this.state.todos];
    const updatedTodos = todos.map((todo, todoIndex) => {
      if (index == todoIndex) {
        return {
          ...todo,
          text: e.target.value
        };
      } else {
        return todo;
      }
    });
    this.setState({
      ...this.state,
      todos: updatedTodos
    });
  };

  handleUpdateSubmit(e, index) {
    e.preventDefault();
    const todos = [...this.state.todos];
    const updatedTodos = todos.map((todo, todoIndex) => {
      if (index == todoIndex) {
        return {
          ...todo,
          editMode: false
        };
      } else {
        return todo;
      }
    });
    this.setState(
      {
        ...this.state,
        todos: updatedTodos
      },
      () => console.info(this.state)
    );
  }

  render() {
    return (
      <div>
        <form onSubmit = {e => this.handleSubmit(e)}>
          <input
            type = "text"
            class = "form-control mb-2"
            placeholder = "enter a todo..."
            onChange = {e => this.handleChangeEvent(e.target.value)}
            value = {this.state.userInput}
          />
          <button type = "submit" class = "btn btn-primary">
            Submit
          </button>
        </form>

        <ul class = "list-group">
          {this.state.todos.map((todos, index) => {
            return (
              <Todo
                todos = {todos}
                todoIndex = {index}
                handleUpdateSubmit = {this.handleUpdateSubmit}
                handleUpdateChange = {this.handleUpdateChange}
                handleEdit = {this.handleEdit}
                handleDelete = {this.handleDelete}
              />
            );
          })}
        </ul>
      </div>
    );
  }
}
export default TodoListt;

Сделать

import React from "react";

class Todo extends React.Component {
  state = {
    hovered: false
  };

  handleMouseEnter = () => {
    this.setState({
      hovered: true
    });
  };

  handleMouseLeave = () => {
    this.setState({
      hovered: false
    });
  };

  render() {
    const {
      todos,
      todoIndex,
      handleUpdateSubmit,
      handleUpdateChange,
      handleEdit,
      handleDelete
    } = this.props;

    const { hovered } = this.state;
    return (
      <div
        onMouseEnter = {this.handleMouseEnter}
        onMouseLeave = {this.handleMouseLeave}
      >
        {todos.editMode ? (
          <form onSubmit = {e => handleUpdateSubmit(e, todoIndex)}>
            <input
              value = {todos.text}
              onChange = {e => handleUpdateChange(e, todoIndex)}
            />
          </form>
        ) : (
          <li
            key = {todos.key}
            class = "list-group-item"
            onDoubleClick = {() => handleEdit(todoIndex)}
          >
            {todos.text}
            <div
              class = "delButton"
              style = {{ display: hovered ? "block" : "none" }}
            >
              <button
                class = "btn btn-danger"
                onClick = {() => handleDelete(todoIndex)}
              >
                Remove
              </button>
            </div>
          </li>
        )}
      </div>
    );
  }
}

export default Todo;

Другие вопросы по теме