У меня есть список дел. Я пытаюсь реализовать функцию, при которой при наведении курсора на задачу (элемент 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;
Эй, Донни! Только что написал вам еще один ответ, вытекающий из вашего вчерашнего вопроса о доступе к реквизиту в массиве. Дайте знать, если у вас появятся вопросы. Я разбил код на части, чтобы у вас был отдельный компонент Todo для каждого элемента :)



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вы можете легко создать это поведение с помощью 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;
Я бы попробовал выделить
liкак отдельный компонент и инкапсулировать в него вашу логику, чтобы у каждой задачи было свое состояние.