Как переключить флажок в приложении reactjs? не работает с моим кодом

#reactjs

#reactjs

Вопрос:

Я вхожу в reactjs и создаю простое приложение Todo, как показано ниже. Однако, когда я пытаюсь переключить флажок, они не переключаются, а также ошибка компиляции не отображается.

введите описание изображения здесь

 1. Used the following command to create app  
command: npx create-react-app test-app

* Folder Structure
  - node_modules
  - publics
  - src
     - App.css
     - App.js
     - App.test.js
     - index.css
     - index.js
     - TodoItem.js --
     - todosData.js --
     - ....
  

Я внес изменения только в 3 файла. Они App.js, TodoItems.js, todosData.js. Весь вставленный код взорван.

App.js

 import React from "react"
import TodoItem from "./TodoItem"
import todosData from "./todosData"

class App extends React.Component {
    constructor() {
        super()
        this.state = {
            todos: todosData
        }
        this.handleChange = this.handleChange.bind(this)
    }
    
    handleChange(id) {
        this.setState(prevState => {
            const updatedTodos = prevState.todos.map(todo => {
                if (todo.id === id) {
                    todo.completed = !todo.completed
                }
                return todo
            })
            return {
                todos: updatedTodos
            }
        })
    }
    
    render() {
        const todoItems = this.state.todos.map(item => <TodoItem key={item.id} item={item} handleChange={this.handleChange}/>)
        
        return (
            <div className="todo-list">
                {todoItems}
            </div>
        )    
    }
}

export default App  

TodoItems.js

 import React from "react"

function TodoItem(props) {
    return (
        <div className="todo-item">
            <input 
                type="checkbox" 
                checked={props.item.completed} 
                onChange={() => props.handleChange(props.item.id)}
            />
            <p>{props.item.text}</p>
        </div>
    )
}

export default TodoItem  

todosData.js

 const todosData = [
    {
        id: 1,
        text: "Take out the trash",
        completed: true
    },
    {
        id: 2,
        text: "Grocery shopping",
        completed: false
    },
    {
        id: 3,
        text: "Clean gecko tank",
        completed: false
    },
    {
        id: 4,
        text: "Mow lawn",
        completed: true
    },
    {
        id: 5,
        text: "Catch up on Arrested Development",
        completed: false
    }
]

export default todosData  

Ответ №1:

Вот краткий рабочий фрагмент, иллюстрирующий функциональную реализацию вашей установки.

Он передает обратный вызов в setState и использует Array.find() для получения ссылки на задачу, которую мы хотим изменить на основе переданного id .

 <script src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>
<div id="App"></div>
<script type="text/babel">
  const { useState} = React;
  const todosData = [
    {
        id: 1,
        text: "Take out the trash",
        completed: true
    },
    {
        id: 2,
        text: "Grocery shopping",
        completed: false
    },
    {
        id: 3,
        text: "Clean gecko tank",
        completed: false
    },
    {
        id: 4,
        text: "Mow lawn",
        completed: true
    },
    {
        id: 5,
        text: "Catch up on Arrested Development",
        completed: false
    }
];

function App() {
    const [todos, setTodos] = useState(todosData);

    const handleChange = (id) => {
      setTodos(prevTodos => {
        const todo = prevTodos.find(todo => todo.id === id);
        todo.completed = !todo.completed;
        return [...prevTodos];
      });
    }
  
    return (
      <div className="todo-list">
        {todos.map(item => <TodoItem key={item.id} item={item} handleChange={handleChange} />)}
      </div>
    )    
}

function TodoItem({item, handleChange}) {
    return (
        <div className="todo-item">
            <input 
                type="checkbox" 
                checked={item.completed} 
                onChange={() => handleChange(item.id)}
            />
            <p>{item.text}</p>
        </div>
    )
}

ReactDOM.render(<App />, document.getElementById('App'));

 </script>  

Ответ №2:

Вы не передаете фактическое значение ввода / флажка в состояние, что упрощает вашу работу по сравнению с реализацией изменения значения самостоятельно.

 import React from "react"

function TodoItem(props) {
    return (
        <div className="todo-item">
            <input 
                type="checkbox" 
                checked={props.item.completed} 
                onChange={val=> props.handleChange(props.item.id, val.target.checked)}
            />
            <p>{props.item.text}</p>
        </div>
    )
}

export default TodoItem  

Также внесите небольшое изменение в handleChange, чтобы использовать как идентификатор, так и значение

 handleChange(id, val) {
        this.setState(prevState => {
            const updatedTodos = prevState.todos.map(todo => {
                if (todo.id === id) {
                    todo.completed = val
                }
                return todo
            })
            return {
                todos: updatedTodos
            }
        })
    }  

Ответ №3:

Вы можете обрабатывать свое состояние следующим образом

 handleChange = (id) => {
      const currState = {
         ...this.state,
      };
      const upgratedTodo = currState.todos.map((todo) => {
         if (todo.id === id) {
            todo.completed = !todo.completed;
         }
         return todo;
      });
      this.setState({
        todos: upgratedTodo,
      })
   };