繁体   English   中英

在 React todo 应用程序中单击时复选框不会更改其值

[英]Checkbox doesn't change its value on click in React todo application

请帮我解决这个问题,我不明白我做错了什么。 因此,当我单击复选框时,值不会更改(如果在单击单击时默认为true ,则它应该为false )。 为此,在todoList组件的onChange中,我正在调用handleClick函数,在那里我更改了todo.completed值(基本上是切换值)。

App.jshandleClick方法中,当从 map 函数返回值之前执行console.log(todo)切换正常,但它没有在updatedTodo更新。

应用程序.js

import TodosData from "./todoData";
import TodoList from "./todoList";
import "./styles.css";

class App extends Component {
  constructor() {
    super();
    this.state = {
      todos: TodosData
    }
    this.handleChange = this.handleChange.bind(this)
  }

  handleChange(id) {
    this.setState(prevState => {
      const updatedTodo = prevState.todos.map(todo => {
        // console.log(updatedTodo);
        if(todo.id === id) {
          console.log("before the opt "+todo.completed);
          todo.completed = !todo.completed
          console.log("after the opt "+todo.completed);
        }
        //console.log(todo);
        return todo;
      })
      console.log(updatedTodo);
      return {
        todos: updatedTodo
      }
    });
  }

  render() {

    const todoDataComponents = this.state.todos.map(item => {
      return <TodoList key = {item.id} item = {item} handleChange = {this.handleChange} />
    })
    return (
      <div className="todo-list">{todoDataComponents}</div>
    );
  }
}

export default App;

待办事项列表.jsx



class TodoList extends Component {
    constructor(props) {
        super(props);
        this.state = {}
    }
    render() {
        // console.log(this.props)
        return (
            <div className="todo-item">
                <input
                    type="checkbox"
                    checked={this.props.item.completed}
                    onChange = {() => this.props.handleChange(this.props.item.id)}
                />
                <p>{this.props.item.text}</p>
            </div>
        );
    }
}

export default TodoList;

todoData.js

const TodosData = [
    { id: 1, text: "Coding", completed: true },
    { id: 2, text: "Exercise", completed: false },
    { id: 3, text: "Learning", completed: true },
    { id: 4, text: "Programming", completed: true },
    { id: 5, text: "inspire", completed: false },
    { id: 6, text: "motivation", completed: true }
];

export default TodosData;

我在您的handleChange()方法handleChange()不到任何错误,它应该可以正常工作。 但是,我刚刚更新了您的一些代码,您可以在下面进行测试。

我更改了您的TodoList的名称,因为它实际上不是一个列表而是一个项目。 我还把它改成了一个功能组件,因为它只是展示性的,不需要有自己的状态。 与其在input之后添加p标签,不如使用label使其可访问。

我并没有真正更改您的handleChange()方法中的任何内容,只是删除了console.log并且它按预期工作。

更新:您正在使用React.StrictMode ,其中 React 在开发中渲染所有内容两次。 当您的handleChange()运行两次时,它会两次设置被点击的待办事项的completed状态,使其设置回其原始状态。 所以,如果这是false的第一渲染其设置为true的点击,但它再次呈现和第二个它的回false 你不会注意到它,因为它非常快。

为了避免它,你需要避免改变任何东西。 所以我更新了你的onChange处理程序,如果已completed属性发生更改,它会返回一个新对象。

随意运行下面的代码片段并单击复选框或项目文本。

 const TodosData = [ { id: 1, text: 'Coding', completed: true }, { id: 2, text: 'Exercise', completed: false }, { id: 3, text: 'Learning', completed: true }, { id: 4, text: 'Programming', completed: true }, { id: 5, text: 'Inspire', completed: false }, { id: 6, text: 'Motivation', completed: true }, ]; function TodoItem(props) { const { handleChange, item } = props; return ( <div className="todo-item"> <input type="checkbox" id={`item-${item.id}`} checked={item.completed} onChange={() => handleChange(item.id)} /> <label htmlFor={`item-${item.id}`}>{item.text}</label> </div> ); } class App extends React.Component { constructor() { super(); this.state = { todos: TodosData, }; this.handleChange = this.handleChange.bind(this); } handleChange(id) { this.setState((prevState) => { const updatedTodo = prevState.todos.map((todo) => { return todo.id === id ? { ...todo, completed: !todo.completed, } : todo; }); return { todos: updatedTodo, }; }); } render() { const { todos } = this.state; return ( <div className="todo-list"> {todos.map((item) => ( <TodoItem key={item.id} item={item} handleChange={this.handleChange} /> ))} </div> ); } } ReactDOM.render( <React.StrictMode> <App /> </React.StrictMode>, document.getElementById('root') );
 body { font-family: sans-serif; line-height: 1.6; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script> <div id="root"></div>

您可以在一行中完成,而不是使用额外的变量。 你能看看这是否适合你。

handleChange(id) {
    this.setState(prevState => prevState.map(todo => todo.id === id ? {...todo, completed: !todo.completed} : todo )
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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