我正在尝试使用 React.js 创建我的第一个 Todo 列表。我正在尝试从
更改状态const [todos, setTodos] = useState([])
致:
const [todos, setTodos] = useState({
todo: [],
isCompleted: false,
})
只是尝试添加一个 isCompleted 状态。但是,当我更改它时,从以前工作的地图运行我的应用程序时出现错误。错误在标题中。
谁能告诉我哪里出了问题?
代码:
TodosApp.js
import React, { useState } from "react"
import Todos from "./Todos"
const TodoApp = () => {
const [todos, setTodos] = useState({
todo: [],
isCompleted: false,
})
const [input, setInput] = useState("")
const handleCurrentInput = (e) => {
setInput(e.target.value)
}
const handleSubmit = (e) => {
e.preventDefault()
console.log(input)
setInput("")
setTodos({
...todos,
task: input,
isCompleted: false,
})
}
const handleDelete = ({ index }) => {
const newTodos = [...todos]
newTodos.splice(index, 1)
setTodos(newTodos)
}
return (
<div id="todoForm">
<div class="container">
<div class="todo_form">
<div class="todo_input">
<form onSubmit={handleSubmit}>
<input
type="text"
id="input_todo"
onChange={handleCurrentInput}
value={input}
/>
</form>
<Todos todos={todos} handleDelete={handleDelete} />
</div>
</div>
</div>
</div>
)
}
export default TodoApp
Todos.js
import React, { useState } from "react"
const Todos = (props) => {
return (
<ul>
{props.todos.map((todo, index) => {
return (
<li key={todo}>
{todo}
<button onClick={() => props.handleDelete({ index })}>
Delete
</button>
</li>
)
})}
</ul>
)
}
export default Todos
答案 0 :(得分:2)
您需要关注每个 todo
项目,包括 2 个道具 task, isCompleted
而不是 isCompleted
的 todos
。
const [todos, setTodos] = useState([]);
var newTodo = {
task: 'React JS',
isCompleted: false
};
setTodos([...todos, newTodo]);
然后您的 todos
的结构如下所示:
[
{
task: 'Study React JS',
isCompleted: false
},
{
task: 'Study React Redux',
isCompleted: false
},
];
答案 1 :(得分:1)
你的状态是一个包含一系列待办事项的对象。这是您传递给 Todos
组件的内容。
所以你有两个选择:
todos.todos
作为道具传递或isCompleted
似乎应该是每个待办事项的一部分,因为每个待办事项都应该完成而不是列表本身。如果每个待办事项 isCompleted
所以你的状态是 const [todos, setTodos] = useState([])
我希望我的意思很清楚。从手机输入这个并不容易:-)
答案 2 :(得分:0)
这是因为您没有设置正确的方式,todos
被错误的值覆盖。你应该写:
// handleSubmit
setTodos(s => {
...s,
task: input,
isCompleted: false,
});
和
// handleDelete
const newTodos = [...todos]
newTodos.splice(index, 1)
setTodos(s => ({ ...s, todos: newTodos }))
答案 3 :(得分:0)
工作应用:Stackblitz
import React, { useState, useEffect } from "react";
const TodoApp = () => {
/* initialize todos with array
instead of an object ?*/
const [todos, setTodos] = useState([]);
const [input, setInput] = useState("");
const handleCurrentInput = e => {
setInput(e.target.value);
};
const handleSubmit = e => {
e.preventDefault();
console.log(input);
/* update the state by appending an object having
key todo and isCompleted to copy of our main state,
todos.?
*/
setTodos([...todos, { todo: input, isCompleted: false }]);
setInput("");
};
const handleDelete = ({ index }) => {
const newTodos = [...todos];
newTodos.splice(index, 1);
setTodos(newTodos);
};
useEffect(() => {
console.log(JSON.stringify(todos));
}, [todos]);
return (
<div id="todoForm">
<div class="container">
<div class="todo_form">
<div class="todo_input">
<form onSubmit={handleSubmit}>
<input
type="text"
id="input_todo"
onChange={handleCurrentInput}
value={input}
/>
</form>
<Todos todos={todos} handleDelete={handleDelete} />
</div>
</div>
</div>
</div>
);
};
export default TodoApp;
const Todos = props => {
return (
<>
<ul>
{props.todos.map((todo, index) => {
return (
<li key={index}>
{/**use null propogation to avoid accessing the null todo value which will not exist in first render. */}
{todo?.todo}
<button onClick={() => props.handleDelete({ index })}>
Delete
</button>
</li>
);
})}
</ul>
</>
);
};
答案 4 :(得分:0)
isCompleted
应该与每个待办事项相关联。
因此,您应该使用 todos
作为数组并将对象存储在该数组中。每个对象都将具有 isCompleted
和 task
属性以及唯一的 Id
。
const [todos, setTodos] = useState([]);
您的提交输入如下所示:
const handleSubmit = (e) => {
e.preventDefault();
const todo = {
task: input,
id: new Date().getTime().toString(),
isCompleted: false
};
const updatedTodos = [...todos, todo];
setTodos(updatedTodos);
console.log(updatedTodos);
setInput("");
};
注意:要生成唯一 ID,您可以使用 uuid
库。我在此处使用 id: new Date().getTime().toString()
生成了唯一 ID。
完整工作代码沙盒链接: https://codesandbox.io/s/todosissue-2mc26?file=/src/TodoApp.js
也修改了 handleDelete
函数 :)