我正在使用React Hooks构建一个简单的“待办事项列表”。现在我有两个问题:
1)前两个列表项具有相同的“ id”值(即使我增加了计数器...)
2)仅在双击后选中并更新复选框
我将很感谢您的提示,线索,评论,建议和解决方案! :-)
这是“ ToDoList”组件:
import React, { useState, useEffect } from 'react';
import ListItem from './ToDoItem';
const ToDoList = () => {
let [counter, setCounter] = useState(1);
let initialItem = {
id: counter,
name: '',
time: '',
finished: false,
}
const [tasks, setTasks] = useState([]);
useEffect(() => console.log('THE ARRAY OF TASKS', tasks), [tasks]);
const [task, setTask] = useState(initialItem);
const handleSubmit = (e) => {
e.preventDefault();
setCounter(counter + 1);
setTask(prevState => {
return { ...prevState, id: counter}
});
setTasks([...tasks, task]);
setTask(initialItem);
}
const deleteItem = (id) => {
let newTasks = tasks.filter((item, index) => {
return index !== id
});
setTasks(newTasks);
}
const handleCheckbox = (val, id) => {
tasks.map((element) => {
if (element.id === id) {
element.finished = val
}
})
console.log('UPDATED TASKS', tasks)
}
return (
<div>
<form onSubmit={handleSubmit}>
<input placeholder="Add a task" value={task.name} onChange={(e) => {
let value = e.target.value;
setTask(prevState => {
return { ...prevState, name: value }
})
}}></input>
<input placeholder="Add time" value={task.time} onChange={(e) => {
let value = e.target.value;
setTask(prevState => {
return { ...prevState, time: value }
})
}}></input>
<button>Submit</button>
</form>
<ListItem tasks={tasks} delete={deleteItem} checked={handleCheckbox} />
</div>
)
}
export default ToDoList;
这是“ ListItem”组件:
import React, { useState } from 'react';
function ListItem(props) {
const tasks = props.tasks;
const [isChecked, setIsChecked] = useState(false);
return tasks.map((element, index) => {
return <li key={index}>
{element.name}: {element.time}
<button onClick={() => props.delete(index)}>delete</button>
<label className="container">
<input type="checkbox" checked={element.finished}
onChange={(e) => setIsChecked(!isChecked)}
onClick={(e) => {props.checked(isChecked, element.id);}}>
</input>
<span className="checkmark"></span>
</label>
</li>
})
}
export default ListItem;
答案 0 :(得分:1)
状态设置器是异步的,这意味着setCounter之后的行可能会在计数器值实际更新之前运行。
在您的情况下,似乎唯一一次更新计数器是在添加新任务之前,因此您可以重构代码,以便当计数器更改时,任务的添加就会生效:
const handleSubmit = (e) => {
e.preventDefault();
setCounter(count => count + 1);
};
useEffect(() => {
setTask(prevState => {
return { ...prevState, id: counter}
});
setTasks([...tasks, task]);
setTask(initialItem);
}, [counter]);
尽管现在,在setTask尚未完成时,使用task可能会遇到相同的问题。但是,您可能不需要设置任务,使用任务然后再将任务重置为这种状态。尝试以下方法:
const handleSubmit = (e) => {
e.preventDefault();
setCounter(count => count + 1);
};
useEffect(() => {
const newTask = {...task, id: counter};
setTasks([...tasks, task]);
setTask(initialItem);
}, [counter]);
这样,无需任何代码就可以等待任务状态更新,也不会出现竞争条件。 (这假设“任务”在提交之前不可能立即更改,因此在创建新对象时只需拉出“任务”的当前值即可。)