React JS - 单击后无法维护和呈现状态值
React JS - Can't maintain and render the state values after onclick
我按照教程使用功能组件制作待办事项,当我尝试删除待办事项列表中的项目或将其标记为完成时遇到问题。我尝试在 deleteHandler 和 completeHandler 中都使用 prev 状态值。列表中的值按预期工作,但是当我从列表中删除一项时,整个状态值都被破坏了。我已经记下了我拥有 deleteHandler 和 completeHandler 的组件以及其他两个组件。任何人都请指导我在代码中缺少什么。提前致谢。
我有三个组件(表单、TodoList 和 Todos)。表单组件是那里的父组件,只有我将状态值作为道具传递给 TodoList 和 Todos 组件。
待办组件:
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;
TodoList 组件:
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
在表单标签内,您需要在 deleteHandler
和 completeHandler
中添加 preventDefault()
以避免页面刷新。
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;
})
);
};
我按照教程使用功能组件制作待办事项,当我尝试删除待办事项列表中的项目或将其标记为完成时遇到问题。我尝试在 deleteHandler 和 completeHandler 中都使用 prev 状态值。列表中的值按预期工作,但是当我从列表中删除一项时,整个状态值都被破坏了。我已经记下了我拥有 deleteHandler 和 completeHandler 的组件以及其他两个组件。任何人都请指导我在代码中缺少什么。提前致谢。
我有三个组件(表单、TodoList 和 Todos)。表单组件是那里的父组件,只有我将状态值作为道具传递给 TodoList 和 Todos 组件。
待办组件:
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;
TodoList 组件:
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
在表单标签内,您需要在 deleteHandler
和 completeHandler
中添加 preventDefault()
以避免页面刷新。
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;
})
);
};