每次选中/取消选中复选框时,我都会尝试更新渲染的卡片。目前,我在想办法更新todos状态时遇到了相当长一段时间的麻烦,该状态是一个包含多个JSON的数组,例如:
[{"_id":"fhrgiu34hnt","todo_description":"Lunch","todo_responsible":"1:30PM","todo_priority":"High","todo_completed":true,"todo_id":"fhrgiu34hnt"},{"_id":"fgvjhbansfgki35sn","todo_description":"Dinner","todo_responsible":"7:45PM","todo_priority":"High","todo_completed":true,"todo_id":"fgvjhbansfgki35sn"},{"_id":"sfgvhio3t58","todo_description":"Supper","todo_responsible":"10:30PM","todo_priority":"Medium","todo_completed":false}]
当通过onChange调用changedBox时,值会更新,但由于(错误地(尝试比较组件中的todo而没有重新渲染?当我手动刷新页面时,复选框的更新值将再次呈现。有没有一种方法可以更新组件Todo中选中的Todo,使其正确呈现?
以下是我目前拥有的:
import React, {Component} from 'react';
import {useState, useEffect} from 'react';
import {Link} from 'react-router-dom';
import axios from 'axios';
const changedBox = (e, props) => {
const completed = e;
console.log("Inside changedBox");
console.log("Trying to update - ID: " + props.todo._id);
console.log("Checkbox is currently: " + completed);
const obj = {
todo_id: props.todo._id,
todo_description: props.todo.todo_description,
todo_responsible: props.todo.todo_responsible,
todo_priority: props.todo.todo_priority,
todo_completed: completed
};
axios.post('example.com/api', obj)
.then(response => console.log(response.data));
};
function Todo (props) {
let [t] = useState(props.todo);
console.log(t)
console.log(JSON.stringify(t));
useEffect(() => {
console.log("Inside useEffect");
axios.get('example.com/api')
.then(response => {
t = props.todo;
})
.catch(function (error) {
console.log(error);
})
})
return (
<div className="card" key={props.todo._id}>
<div className="card-body">
<input type="checkbox" id={props.todo._id} checked={props.todo.todo_completed}
onChange={event => changedBox(!props.todo.todo_completed, props)}/>
<label htmlFor={props.todo._id}/>
<div className="card-title">
<h4> {props.todo.todo_description} </h4>
<h6> {props.todo.todo_responsible} </h6>
<h6> {props.todo._id ? props.todo._id : "No ID yet"} </h6> {/* Debugging */}
<h6> {props.todo.todo_priority} </h6> {/* Debugging */}
<span
className="badge badge-info"> {props.todo.todo_completed ? "Completed" : "Not Completed"} </span>
</div>
<div className="dropdown card-options">
<Link to={"/edit/" + props.todo._id}
style={{color: 'inherit', textDecoration: 'inherit'}}>
<button className="btn-options" type="button">
<i className="fas fa-ellipsis-v"/>
</button>
</Link>
</div>
</div>
</div>
)
}
class TodosList extends Component {
_isMounted = false;
constructor(props) {
super(props);
this.state = {
todos: []
};
}
componentDidMount() {
this._isMounted = true;
axios.get('example.com/api')
.then(response => {
if (this._isMounted) {
this.setState({todos: response.data});
}
})
.catch(function (error) {
console.log(error);
})
}
componentDidUpdate(prevProps, prevState, ss) {
console.log("prevState.todos: " + prevState.todos);
console.log(JSON.stringify(prevState.todos));
console.log("Comparing JSON.stringify(this.state.todos) !== JSON.stringify(prevState.todos): " + (JSON.stringify(this.state.todos) !== JSON.stringify(prevState.todos)));
if (JSON.stringify(this.state.todos) !== JSON.stringify(prevState.todos)) {
console.log("Inside componentDidUpdate - Attempting to update!");
axios.get('example.com/api')
.then(response => {
this.setState({todos: response.data});
})
.catch(function (error) {
console.log(error);
});
}
}
componentWillUnmount() {
this._isMounted = false;
}
todoList() {
return this.state.todos.map(function (currentTodo, i) {
console.log("Todo ID: " + currentTodo._id + ", Num: " + i);
return <Todo todo={currentTodo} key={i} ind={i}/>;
});
}
render() {
return (
<div className="card-container">
<h3>List</h3>
{this.todoList()}
</div>
)
}
}
export default TodosList;
这里有一些事情可以做得更好。
首先,useState返回2个元素的数组,第一个是数据,第二个是updater函数,因此,每当你使用useState并且想要更新状态时,都要这样做:
const [data, setData] = useState('some data');
setData('I want to update it');
然后组件将重新渲染。
这应该是固定的
.then(response => {
// t = props.todo;
setTodo(props.todo);
})
changedBox
方法不会导致组件的重新发布,因为它没有改变状态,请再次使用setTodo
。
const obj = {
todo_id: props.todo._id,
todo_description: props.todo.todo_description,
todo_responsible: props.todo.todo_responsible,
todo_priority: props.todo.todo_priority,
todo_completed: completed
};
setTodo(obj)
我看到您正在使用钩子和基于类的组件的混合,尝试使用其中一个,这将使您的代码更加一致。