簡體   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