React JS -不能维护和渲染onclick后的状态值



我遵循了一个教程,使用功能组件制作待办事项,当我试图删除或标记为完成待办事项列表中的项目时,我面临的问题。我试图在deleteHandler和completeHandler中使用先前的状态值。列表中的值按预期工作,但是当我从列表中删除一个项目时,整个状态值都被销毁了。我已经写下了我拥有deleteHandler和completeHandler以及其他两个组件的组件。任何人请指导我,我在代码中缺少什么。提前谢谢。

我有三个组件(表单,TodoList和Todos)。表单组件是父组件,只有我将状态值作为道具传递给TodoList和Todos组件。

Todo组件:

const Todo = ({ text, todo, todos, setTodos }) => {
const deleteHandler = (prevState) => {
setTodos(todos.filter((el) => el.id !== todo.id));
// console.log(todo);
};
const completeHandler = () => {
setTodos(
todos.map((item) => {
if (item.id === todo.id) {
return {
...item,
completed: !item.completed,
};
}
return item;
})
);
};
return (
<div className="todo">
<li className={`todo-item ${todo.completed ? "completed" : ""}`}>
{text}
</li>
<button onClick={completeHandler} className="complete-btn">
<i className="fas fa-check"></i>
</button>
<button onClick={deleteHandler} className="trash-btn">
<i className="fas fa-trash"></i>
</button>
</div>
);
};
export default Todo;

基于组件:

const TodoList = ({ todos, setTodos, filterTodos }) => {
// console.log("prp", todos);
return (
<div className="todo-container">
<ul className="todo-list">
{todos && todos.length
? filterTodos.map((todo) => (
<Todo
setTodos={setTodos}
todos={todos}
todo={todo}
key={todo.id}
text={todo.text}
id={todo.id}
/>
))
: ""}
</ul>
</div>
);
};
export default TodoList;

表单组件:

const Form = () => {
const [inputText, setInputText] = useState("");
const [todos, setTodos] = useState([]);
const [status, setStatus] = useState("all");
const [filterTodos, setFilterTodos] = useState([]);
// eslint-disable-next-line react-hooks/exhaustive-deps
const filterHandler = () => {
switch (status) {
case "completed":
setFilterTodos(todos.filter((todo) => todo.completed === true));
break;
case "incompleted":
setFilterTodos(todos.filter((todo) => todo.completed === false));
break;
default:
setFilterTodos(todos);
break;
}
};
useEffect(() => {
filterHandler();
}, [todos, status, filterHandler]);
const inputHandler = (e) => {
setInputText(e.target.value);
};
const submitTodohandler = (e) => {
e.preventDefault();
setTodos([
...todos,
{ text: inputText, completed: false, id: Math.random() * 1000 },
]);
setInputText(" ");
};
const statusHandler = (e) => {
console.log(e.target.value);
setStatus(e.target.value);
};
return (
<form>
<input
value={inputText}
onChange={inputHandler}
type="text"
className="todo-iput"
/>
<button className="todo-button" type="submit" onClick={submitTodohandler}>
<i className="fas fa-plus-square"></i>
</button>
<div className="select">
<select name="todos" className="filter-todo" onChange={statusHandler}>
<option value="all">All</option>
<option value="completed">completed</option>
<option value="incompleted">Incompleted</option>
</select>
</div>
<TodoList setTodos={setTodos} todos={todos} filterTodos={filterTodos} />
</form>
);
};
export default Form;

由于您的TodoList在表单标签内,您需要在deleteHandlercompleteHandler中添加preventDefault()以避免页面刷新。

codesandbox

const deleteHandler = (e) => {
e.preventDefault();
setTodos(todos.filter((el) => el.id !== todo.id));
// console.log(todo);
};
const completeHandler = (e) => {
e.preventDefault();
setTodos(
todos.map((item) => {
if (item.id === todo.id) {
return {
...item,
completed: !item.completed
};
}
return item;
})
);
};

最新更新