简体   繁体   English

复选框在react js的todo中不起作用

[英]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.最大的问题是onDeleteonChangeCheckboxaddTodo处理程序中的状态变化。 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>;
};

编辑 checkboxes-are-not-working-in-todo-in-react-js

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM