"TypeError: props.todos.map is not a function" can't figure out what the cause is?
"TypeError: props.todos.map is not a function" can't figure out what the cause is?
我正在尝试使用 React.js 创建我的第一个待办事项列表。我正在尝试更改状态
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
您的状态是一个包含待办事项数组的对象。这就是您传递给 Todos
组件的内容。
所以你有两个选择:
- 将
todos.todos
作为道具传递或
- (更好的方法)重新考虑你的状态。
isCompleted
似乎它应该是每个待办事项的一部分,因为每个待办事项都应该完成而不是列表本身。如果每个待办事项 isCompleted
,则列表已完成
所以你的状态是 const [todos, setTodos] = useState([])
我希望你明白我的意思。从 phone 中输入这个并不容易 :-)
您需要专注于每个 todo
项目,包括 2 个道具 task, isCompleted
而不是 todos
的 isCompleted
。
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
},
];
因为你没有设置正确的方式,todos
被错误的值覆盖了。你应该写:
// handleSubmit
setTodos(s => {
...s,
task: input,
isCompleted: false,
});
和
// handleDelete
const newTodos = [...todos]
newTodos.splice(index, 1)
setTodos(s => ({ ...s, todos: newTodos }))
工作应用: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>
</>
);
};
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
完整的工作代码沙盒 LINK: https://codesandbox.io/s/todosissue-2mc26?file=/src/TodoApp.js
也修改了handleDelete
函数:)
我正在尝试使用 React.js 创建我的第一个待办事项列表。我正在尝试更改状态
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
您的状态是一个包含待办事项数组的对象。这就是您传递给 Todos
组件的内容。
所以你有两个选择:
- 将
todos.todos
作为道具传递或 - (更好的方法)重新考虑你的状态。
isCompleted
似乎它应该是每个待办事项的一部分,因为每个待办事项都应该完成而不是列表本身。如果每个待办事项isCompleted
,则列表已完成 所以你的状态是const [todos, setTodos] = useState([])
我希望你明白我的意思。从 phone 中输入这个并不容易 :-)
您需要专注于每个 todo
项目,包括 2 个道具 task, isCompleted
而不是 todos
的 isCompleted
。
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
},
];
因为你没有设置正确的方式,todos
被错误的值覆盖了。你应该写:
// handleSubmit
setTodos(s => {
...s,
task: input,
isCompleted: false,
});
和
// handleDelete
const newTodos = [...todos]
newTodos.splice(index, 1)
setTodos(s => ({ ...s, todos: newTodos }))
工作应用: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>
</>
);
};
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()
.
完整的工作代码沙盒 LINK: https://codesandbox.io/s/todosissue-2mc26?file=/src/TodoApp.js
也修改了handleDelete
函数:)