建立一个反应任务列表,我有一个非常具体的错误,需要一些帮助。我添加了向每个待办事项添加标签的功能。它在列表中的最后一个待办事项上效果很好,但是如果我尝试在列表中更高级别的任何待办事项中输入内容,它将更新最后一个待办事项的输入字段中的值。这是沙盒链接,因此您可以了解我在说什么:https://codesandbox.io/s/trusting-architecture-xjkbf?file=/src/App.js
我的代码如下。我知道,问题在于在我调用setTag的范围之外声明了[tag,setTag] = useState。我只是不知道我需要在哪里放置它以便工作。 (我复制了所有代码,但可以肯定地确定该问题是Task组件的本地问题)
import React, { useState } from "react";
import "./styles.css";
import todoBlack from "./icons/todoBlack.png";
function TodoForm(props) {
[val, setVal] = useState("");
const handleSubmit = e => {
e.preventDefault();
if (val) {
props.addTask(val);
setVal("");
}
};
return (
<div className="row">
<div className="col-2" />
<div className="col-8">
<form className="py-1" onSubmit={handleSubmit}>
<input
placeholder="New Item"
className="w-100 p-2 border"
type="text"
value={val}
onChange={e => setVal(e.target.value)}
/>
</form>
</div>
</div>
);
}
function Task(props) {
[tag, setTag] = useState("");
const handleSubmit = e => {
e.preventDefault();
if (tag) {
props.addTag(props.index, tag);
setTag("");
}
};
return (
<div
className={props.task.isComplete ? "complete-task" : "incomplete-task"}
>
<li className="row w-100 py-2 mx-0 px-0 border-bottom">
<div className="text-left col-2 todo-button">
<button onClick={() => props.completeTask(props.index)}>
<img src={todoBlack} height="25" alt="todo" />
</button>
</div>
<div className="text-left col-4 my-auto">
<p className="my-1">{props.task.text}</p>
</div>
<div className="text-left col-4 my-auto">
<div>
{props.task.tags
? props.task.tags.map((tag, index) => (
<p
className="mx-1"
key={index}
index={index}
style={{ display: "inline" }}
>
{tag}
<button onClick={() => props.removeTag(props.index, index)}>
x
</button>
</p>
))
: ""}
</div>
<form onSubmit={handleSubmit}>
<input
className="w-50"
placeholder="Add Tag"
type="text"
value={tag}
onChange={e => setTag(e.target.value)}
/>
</form>
</div>
<div className="text-right col-2">
<button type="button" onClick={() => props.removeTask(props.index)} />
</div>
</li>
</div>
);
}
export default function App() {
[tasks, setTasks] = useState([]);
[globalTags, setglobalTags] = useState([]);
const addTask = text => {
const newTasks = [...tasks, { text }];
setTasks(newTasks);
};
const removeTask = index => {
const newTasks = [...tasks];
newTasks.splice(index, 1);
setTasks(newTasks);
};
const completeTask = index => {
const newTasks = [...tasks];
if (!newTasks[index].isComplete) {
newTasks[index].isComplete = true;
} else {
newTasks[index].isComplete = false;
}
setTasks(newTasks);
};
const addTag = (index, text) => {
const newTasks = [...tasks];
if (newTasks[index].tags) {
newTasks[index].tags.push(text);
} else {
newTasks[index].tags = [];
newTasks[index].tags.push(text);
}
setTasks(newTasks);
};
const removeTag = (index, tagIndex) => {
const newTasks = [...tasks];
newTasks[index].tags.splice(tagIndex, 1);
setTasks(newTasks);
};
const taskList = tasks.map((task, index) => (
<Task
key={index}
index={index}
task={task}
completeTask={completeTask}
isComplete={task.isComplete}
removeTask={removeTask}
addTag={addTag}
removeTag={removeTag}
/>
));
return (
<div className="App">
<TodoForm addTask={addTask} />
<ul className="container-fluid">{taskList}</ul>
</div>
);
}
答案 0 :(得分:1)
这是在示例中添加引用的方式。功能组件中没有this
的概念。您需要使用useRef
。 this
悬挂在函数外部,因此始终将其应用于最后一个函数,这就是为什么它适用于最后一个函数而不适用于其他函数的原因