[英]Checkboxes are not working in todo in react js
I'm implementing Todo with checkboxes.我正在使用复选框实现 Todo。 I have a id,content,status properties in the state.我在该州有一个 id、content、status 属性。 Status has 3 states(pending,done, deleted).状态有 3 个状态(待定、完成、已删除)。 There is a checkbox for the todolist.待办事项列表有一个复选框。 If the status is pending then checkbox shouldn't be checked.如果状态为待定,则不应选中复选框。 If the status is done then checkbox should be checked.By default, status is pending.Checkbox should be checked/unchecked according to the status.如果状态已完成,则应选中复选框。默认情况下,状态为待定。应根据状态选中/取消选中复选框。 On deleting the todo then status should be updated to deleted.在删除待办事项时,状态应更新为已删除。 Now I'm struck with checkbox implementation.现在我对复选框的实现感到震惊。 It's not working as per the requirement.它没有按照要求工作。
App.js :应用程序.js:
import React from 'react';
import Todo from './Todo';
import AddTodo from './AddTodo';
class App extends React.Component{
state={
todos:[
{id:1,content:'Buy milk1',status:'pending'},
{id:2, content:'buy carrots1', status: 'pending'},
{id:3,content:'Buy milk2',status:'done'},
{id:4, content:'buy carrots2', status: 'deleted'}
]
}
onDelete=(id)=>{
const todo = this.state.todos.find((todoItem => todoItem.id === id))
todo.status ='deleted';
this.setState([...this.state.todos]);
}
onChangeCheckbox=(id, checked)=>{
const todo = this.state.todos.find((todoItem => todoItem.id === id))
if(checked){
todo.status = 'done'
}
else{
todo.status = 'pending'
}
this.setState([...this.state.todos]);
}
addTodo=(todo)=>{
todo.id=Math.random();
todo.status = "pending";
let todos=[...this.state.todos,todo];
this.setState({todos});
}
render(){
return(
<div>
<h1>Todo's App</h1>
<AddTodo addTodo={this.addTodo} />
<Todo todos={this.state.todos} deleteTodo={this.onDelete} onChangeCheckbox=
{this.onChangeCheckbox} />
</div>
)
}
}
export default App;
AddTodo.js :添加Todo.js :
import React from 'react';
class AddTodo extends React.Component{
state={
content:''
}
handleChange=(e)=>{
this.setState({
content:e.target.value
});
}
handleSubmit=(e)=>{
e.preventDefault();
this.props.addTodo(this.state);
this.setState({
content:''
})
}
render(){
return(
<div>
<form onSubmit={this.handleSubmit}>
<input type='text' onChange={this.handleChange} value={this.state.content}
placeholder="Enter todo" />
<input type="submit" value="Submit"/>
</form>
</div>
);
}
}
export default AddTodo;
Todo.js: Todo.js:
import React, {useState} from 'react';
const Todo=({todos,deleteTodo, onChangeCheckbox})=>{
const [checked, setChecked] = useState(false);
const handleInputChange =(event,id,status)=>{
setChecked(status=='pending' ? !checked: checked)
onChangeCheckbox(id,!checked);
}
const todoList=todos.length ? (
todos.map(todo=>{
return(
<div key={todo.id}>
{(todo.status === 'pending' || todo.status === 'done' )&& (
<div>
{/* <input
type="checkbox"
checked={checked}
onChange={(event)=>handleInputChange(event,todo.id)}
/> */}
<input
type="checkbox"
checked={todo.status === 'pending' ? checked : !checked}
onChange=
{(event)=>handleInputChange(event,todo.id,todo.status)}
/>
<p style={todo.status =='pending'? {color:'red'}:
{color:'green',textDecoration:'line-through'}} >
{todo.content}
</p>
<button onClick={()=>deleteTodo(todo.id)}>Delete</button>
</div>
)}
</div>
)
})
):(
<p>You have no todos</p>
);
return(
<div>
{todoList}
</div>
)
}
export default Todo;
Thanks in advance.. Please find the codesandbox link here: https://codesandbox.io/s/awesome-ganguly-0r054?file=/src/Todo.js提前致谢.. 请在此处找到代码和框链接: https ://codesandbox.io/s/awesome-ganguly-0r054?file =/ src/Todo.js
You have only one checked
state, for every todo
item.对于每个todo
,您只有一个checked
状态。 I'd recommend for you to add checked
state to every item in todos
list.我建议您为todos
列表中的每个项目添加checked
状态。 Then you can find item and change state accordingly然后你可以找到项目并相应地改变状态
You've a few issues with your code.您的代码有一些问题。 The biggest concern is the state mutations in your onDelete
, onChangeCheckbox
, and addTodo
handlers.最大的问题是onDelete
、 onChangeCheckbox
和addTodo
处理程序中的状态变化。 These handlers also incorrectly don't store the todos
array.这些处理程序也错误地不存储todos
数组。
Use functional state updates and map the existing state todos array to a new array, and copy the todo
item that matches by id so you are not mutating state objects.使用功能状态更新并将现有状态 todos 数组映射到新数组,并复制与 id 匹配的todo
项,这样您就不会改变状态对象。
Math.random generates floating point numbers, and as such, makes it extremely difficult to compare with ===
.的Math.random生成浮点数,正因为如此,使得它非常难以与比较===
。 I added a guid to each instead.我为每个添加了一个 guid。
class App extends React.Component {
state = {
todos: [
{ id: uuidV4(), content: "Buy milk1", status: "pending" },
{ id: uuidV4(), content: "buy carrots1", status: "pending" },
{ id: uuidV4(), content: "Buy milk2", status: "done" },
{ id: uuidV4(), content: "buy carrots2", status: "deleted" }
]
};
onDelete = (id) => {
this.setState((prevState) => ({
todos: prevState.todos.map((todo) =>
todo.id === id
? {
...todo,
status: "deleted"
}
: todo
)
}));
};
onChangeCheckbox = (id, checked) => {
this.setState((prevState) => ({
todos: prevState.todos.map((todo) =>
todo.id === id
? {
...todo,
status: checked ? "done" : "pending"
}
: todo
)
}));
};
addTodo = (todo) => {
this.setState((prevState) => ({
todos: [
...prevState.todos,
{
...todo,
id: uuidV4(),
status: "pending"
}
]
}));
};
render() {
return (
<div>
<h1>Todo's App</h1>
<AddTodo addTodo={this.addTodo} />
<Todo
todos={this.state.todos}
deleteTodo={this.onDelete}
onChangeCheckbox={this.onChangeCheckbox}
/>
</div>
);
}
}
There is also no need to store any checked
state in Todo.js
as the checked state is easily derived from your todo.status
property.也不需要在Todo.js
存储任何checked
状态,因为检查状态很容易从您的todo.status
属性派生。 If the status is "done" then check the box.如果状态为“完成”,则选中该框。
You can (should) run your todos
array through a filter first to remove the deleted status todos.您可以(应该)首先通过过滤器运行您的todos
数组以删除已删除状态的待办事项。
const Todo = ({ todos, deleteTodo, onChangeCheckbox }) => {
const todoList = todos.length ? (
todos
.filter(({ status }) => status !== "deleted")
.map((todo) => {
return (
<div key={todo.id}>
<div>
<input
type="checkbox"
checked={todo.status === "done"}
onChange={(event) =>
onChangeCheckbox(todo.id, event.target.checked)
}
/>
<p
style={
todo.status === "pending"
? { color: "red" }
: { color: "green", textDecoration: "line-through" }
}
>
{todo.content}
</p>
<button onClick={() => deleteTodo(todo.id)}>Delete</button>
</div>
<hr />
</div>
);
})
) : (
<p>You have no todos</p>
);
return <div>{todoList}</div>;
};
that's happen because you let the checked status listen to the current component state
and not to the item status.发生这种情况是因为您让检查状态监听current component state
而不是项目状态。 and they are not in sync.而且它们不同步。 so you have two solutions.所以你有两个解决方案。 first pass status value as props to the checked state to let the state changed when the status value updated and i think it is more expensive.首先将状态值作为道具传递给选中的状态,让状态在状态值更新时改变,我认为它更昂贵。 I have other suggestion without the state at all.我还有其他没有国家的建议。
// const [checked, setChecked] = useState(false); remove that, you no longer need it
const handleInputChange =(event,id,status)=>{
let isChecked = status=='pending' ? true: false;
onChangeCheckbox(id, isChecked);
}
also update the input check status还更新输入检查状态
<input
type="checkbox"
checked={todo.status === 'pending' ? false : true}
onChange= {(event)=>handleInputChange(event,todo.id,todo.status)}
/>
https://codesandbox.io/s/competent-hugle-jn22o?file=/src/Todo.js https://codesandbox.io/s/competent-hugle-jn22o?file=/src/Todo.js
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.