Estoy siguiendo el curso gratuito de scrimba de Bob Ziroll sobre React.
La cuestión es que mi código es el mismo que el suyo y ha estado funcionando hasta ahora...
pero ya no funciona.
Aquí está mi código
Aplicación.js
import React, { Component } from "react"; import TodoItem from "./components/TodoItem"; import todosData from "./components/todosData"; class App extends Component { constructor() { super() this.state = { todos: todosData } this.handleChange = this.handleChange.bind(this) } handleChange(id) { this.setState(prevState => { console.log("PrevState Start ", prevState.todos ) const updatedTodos = prevState.todos.map(todo => { if (todo.id === id) { todo.completed = !todo.completed } return todo }) return { todos: updatedTodos } }) console.log("Changed", id) } render() { const todoItem = this.state.todos.map(x => <TodoItem handleChange = {this.handleChange} key={x.id} item={x} /> ) return ( <div> {todoItem} </div> ); } } export default App;Y aquí está el código para TodoItem.js
import React from 'react' function TodoItem(props) { return ( <div> <input type='checkbox' checked={props.item.completed} onChange={() => props.handleChange(props.item.id)} /> <p>{props.item.text}</p> </div> ) } export default TodoItemY aquí está 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 todosDataHe intentado usar una devolución de llamada pero no funciona. Revisé prevState y el estado actualizado, pero no se refleja ningún cambio.
Agradecería su ayuda en esto.
Cuando esté actualizando el state usando setState , debe devolver un nuevo object para decirle a reaccionar que este es el cambio y React lo actualizará en consecuencia.
Demo en vivo
React comparará la referencia de dos objetos y, si no devuelve un nuevo objeto, reaccionará como un mismo objeto. React no se dará cuenta de cuándo no devolverá un nuevo objeto. Solo está actualizando una propiedad de un objeto como:
if (todo.id === id) { todo.completed = !todo.completed }Solo tienes que hacer un pequeño cambio como:
if (todo.id === id) { return { ...todo, completed: !todo.completed }; }Siendo súper curioso, probé tu código y me funciona perfectamente. ¿No es esto lo que querías que pasara? Revisa el fragmento a continuación:
document.onreadystatechange = () => { const { useState, Component } = React; class App extends Component { constructor() { super(); this.state = { todos: todosData, }; this.handleChange = this.handleChange.bind(this); } handleChange(id) { this.setState((prevState) => { console.log("PrevState Start ", prevState.todos); const updatedTodos = prevState.todos.map((todo) => { if (todo.id === id) { todo.completed = !todo.completed; } return todo; }); return { todos: updatedTodos, }; }); console.log("Changed", id); } render() { const todoItem = this.state.todos.map((x) => ( <TodoItem handleChange={this.handleChange} key={x.id} item={x} /> )); return <div>{todoItem}</div>; } } function TodoItem(props) { return ( <div> <input type="checkbox" checked={props.item.completed} onChange={() => props.handleChange(props.item.id)} /> <p>{props.item.text}</p> </div> ); } 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, }, ]; ReactDOM.render(<App />, document.querySelector("#root")); }; <script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script> <div id="root"></div>