Неправильный способ обновления вашего состояния.
Обратите внимание, что в элементе todo вы сделали:
<input type="checkbox" value={todo} onChange={markComplete}></input>
Хотя todo
само по себе является объект, что означает, что при этом:
setTodos(prevState => [...prevState , {...e.target.value , done:true} ]);
Вы в основном неправильно распределили объект. Фактически, результат следующего обновления состояния:
0: {title: "Do the dishes", done: false, id: 123}
1: {title: "wash car", done: false, id: 423}
2: {title: "Buy pen", done: false, id: 323}
3: {0: "[", 1: "o", 2: "b", 3: "j", 4: "e", 5: "c", 6: "t", 7: " ", 8: "O", 9: "b", 10: "j", 11: "e", 12: "c", 13: "t", 14: "]", done: true}
Это объясняет полученную ошибку unique key
.
Одним из возможных решений было бы использование оболочки для обработчика изменений который передает идентификатор элемента и проверенный статус:
function Todo({todo , markComplete}) {
const handleChange = React.useCallback(e => {
markComplete(todo.id, e.target.checked);
}, [todo, markComplete]);
return (
<div>
<input type="checkbox" value={todo.id} onChange={handleChange}></input>
<li>{todo.title}</li>
<div className="spacer"></div>
</div>
)
}
markComplete:
const markComplete = (id, checked) => {
setTodos(prevState => prevState.map(it => it.id === id ? ({ ...it, done: checked }) : it));
}
Я бы также рекомендовал использовать useCallback
в вышеуказанной функции.
Вот скрипка: https://jsfiddle.net/vdzbj16a/