通过对象扩展器更改状态时不会重新渲染
我目前正在尝试清理我的 Todo 应用程序的代码并使用更多的不变性。因此,我替换了handleStatus函数中的代码。
从此:
handleStatus(event) {
let newStatus;
const changeState = event.status == 'done' ? newStatus = 'open' : newStatus = 'done';
//Verkürzen Copy State
let todo = event;
todo.status = newStatus;
this.setState({ todo });
}
到此:
handleStatus(event) {
let newStatus;
const changeState = event.status == 'done' ? newStatus = 'open' : newStatus = 'done';
//Verkürzen Copy State
let todo = {
...event,
status: newStatus
};
this.setState({ todo });
}
各个待办事项的状态发生了更改,但 React 不再渲染相应的部分,因此浏览器中不会发生任何更改。
感谢您的帮助
这是完整的代码...... TodoTable(父母):
import React from "react";
import { InputBar } from "./InputBar";
import { Todo } from "./Todo";
const emptyForm = {
enterTodo: ""
};
export class TodoTable extends React.Component {
constructor(props) {
super(props);
this.state = {
enterTodo: "",
todos: this.props.todos,
status: 'open'
};
this.handleEnterTodo = this.handleEnterTodo.bind(this);
this.handleStatus = this.handleStatus.bind(this);
this.handleCreateTodo = this.handleCreateTodo.bind(this);
this.handleClearTodos = this.handleClearTodos.bind(this);
this.handleDeleteTodo = this.handleDeleteTodo.bind(this);
}
//Textbox Input handler
handleEnterTodo(event) {
this.setState({
enterTodo: event.target.value
});
}
//Status handler
handleStatus(event) {
let newStatus;
const changeState = event.status == 'done' ? newStatus = 'open' : newStatus = 'done';
//Verkürzen Copy State
let todo = {
...event,
status: newStatus
};
this.setState({ todo });
}
//delete todo
handleDeleteTodo(event) {
let todo = this.state.todos;
todo.splice(this.state.todos.indexOf(event), 1)
this.setState({ todo });
}
//Create Todo
handleCreateTodo(event) {
const todo = {
id: this.state.todos.length,
describtion: this.state.enterTodo,
status: 'open'
};
this.setState({
todos: [todo, ...this.state.todos]
})
this.state.enterTodo = emptyForm.enterTodo; // Überarbeiten
}
//Clear Todo List
handleClearTodos(event) {
let CleanedTodos = []
this.state.todos.forEach((element, index) => {
if(this.state.todos[index].status == 'open'){
CleanedTodos.push(this.state.todos[index]);
}
});
this.setState({
todos: CleanedTodos
});
}
render() {
return (
<>
<InputBar
handleCreateTodo={ this.handleCreateTodo }
handleEnterTodo={ this.handleEnterTodo }
enterTodo={ this.state.enterTodo }
handleClearTodos={ this.handleClearTodos }
/>
<Todo
handleStatus={ this.handleStatus }
todos={ this.state.todos }
handleClearTodos={ this.state.handleClearTodos }
handleDeleteTodo= { this.handleDeleteTodo }
/>
</>
);
}
}
Todo(孩子);
import React from "react";
import { FormButton } from "./FormButton";
export class Todo extends React.Component {
render() {
const openTodo = [];
const doneTodo = [];
// just for develope
const lineBreak = <hr></hr>
//Select Open Todo and Done
this.props.todos.forEach((element, index) => {
if(this.props.todos[index].status == 'open'){
let todoOpen = (
//CSS Clases for design open
<div className="openTodos" key={this.props.todos[index].id.toString() }>
{this.props.todos[index].describtion}
<FormButton lable='' onClick= {() => this.props.handleStatus(this.props.todos[index])}/>
<FormButton lable='' onClick= {() => this.props.handleDeleteTodo(this.props.todos[index])}/>
</div>
);
//Push open Todo in Open Array
openTodo.push(todoOpen);
}
else{
let todoDone = (
//CSS Clases for design open
<div className="openTodos" key={this.props.todos[index].id.toString() }>
{this.props.todos[index].describtion}
<FormButton lable='' onClick= {() => this.props.handleStatus(this.props.todos[index])}/>
<FormButton lable='' onClick= {() => this.props.handleDeleteTodo(this.props.todos[index])}/>
</div>
);
//Push done Todo in Done Array
doneTodo.push(todoDone);
}
});
return <>
{openTodo}
{lineBreak}
{doneTodo}
</>;
}
}
I am currently trying to clean up the code of my Todo app a bit and use more immutability. I have therefore replaced the code in the handleStatus function.
From this:
handleStatus(event) {
let newStatus;
const changeState = event.status == 'done' ? newStatus = 'open' : newStatus = 'done';
//Verkürzen Copy State
let todo = event;
todo.status = newStatus;
this.setState({ todo });
}
To this:
handleStatus(event) {
let newStatus;
const changeState = event.status == 'done' ? newStatus = 'open' : newStatus = 'done';
//Verkürzen Copy State
let todo = {
...event,
status: newStatus
};
this.setState({ todo });
}
The status of the respective todo is changed but React no longer renders the corresponding part so that no change takes place in the browser.
Thank you for help
Here is the Full Code....
TodoTable (Parents):
import React from "react";
import { InputBar } from "./InputBar";
import { Todo } from "./Todo";
const emptyForm = {
enterTodo: ""
};
export class TodoTable extends React.Component {
constructor(props) {
super(props);
this.state = {
enterTodo: "",
todos: this.props.todos,
status: 'open'
};
this.handleEnterTodo = this.handleEnterTodo.bind(this);
this.handleStatus = this.handleStatus.bind(this);
this.handleCreateTodo = this.handleCreateTodo.bind(this);
this.handleClearTodos = this.handleClearTodos.bind(this);
this.handleDeleteTodo = this.handleDeleteTodo.bind(this);
}
//Textbox Input handler
handleEnterTodo(event) {
this.setState({
enterTodo: event.target.value
});
}
//Status handler
handleStatus(event) {
let newStatus;
const changeState = event.status == 'done' ? newStatus = 'open' : newStatus = 'done';
//Verkürzen Copy State
let todo = {
...event,
status: newStatus
};
this.setState({ todo });
}
//delete todo
handleDeleteTodo(event) {
let todo = this.state.todos;
todo.splice(this.state.todos.indexOf(event), 1)
this.setState({ todo });
}
//Create Todo
handleCreateTodo(event) {
const todo = {
id: this.state.todos.length,
describtion: this.state.enterTodo,
status: 'open'
};
this.setState({
todos: [todo, ...this.state.todos]
})
this.state.enterTodo = emptyForm.enterTodo; // Überarbeiten
}
//Clear Todo List
handleClearTodos(event) {
let CleanedTodos = []
this.state.todos.forEach((element, index) => {
if(this.state.todos[index].status == 'open'){
CleanedTodos.push(this.state.todos[index]);
}
});
this.setState({
todos: CleanedTodos
});
}
render() {
return (
<>
<InputBar
handleCreateTodo={ this.handleCreateTodo }
handleEnterTodo={ this.handleEnterTodo }
enterTodo={ this.state.enterTodo }
handleClearTodos={ this.handleClearTodos }
/>
<Todo
handleStatus={ this.handleStatus }
todos={ this.state.todos }
handleClearTodos={ this.state.handleClearTodos }
handleDeleteTodo= { this.handleDeleteTodo }
/>
</>
);
}
}
Todo (Child);
import React from "react";
import { FormButton } from "./FormButton";
export class Todo extends React.Component {
render() {
const openTodo = [];
const doneTodo = [];
// just for develope
const lineBreak = <hr></hr>
//Select Open Todo and Done
this.props.todos.forEach((element, index) => {
if(this.props.todos[index].status == 'open'){
let todoOpen = (
//CSS Clases for design open
<div className="openTodos" key={this.props.todos[index].id.toString() }>
{this.props.todos[index].describtion}
<FormButton lable='' onClick= {() => this.props.handleStatus(this.props.todos[index])}/>
<FormButton lable='' onClick= {() => this.props.handleDeleteTodo(this.props.todos[index])}/>
</div>
);
//Push open Todo in Open Array
openTodo.push(todoOpen);
}
else{
let todoDone = (
//CSS Clases for design open
<div className="openTodos" key={this.props.todos[index].id.toString() }>
{this.props.todos[index].describtion}
<FormButton lable='' onClick= {() => this.props.handleStatus(this.props.todos[index])}/>
<FormButton lable='' onClick= {() => this.props.handleDeleteTodo(this.props.todos[index])}/>
</div>
);
//Push done Todo in Done Array
doneTodo.push(todoDone);
}
});
return <>
{openTodo}
{lineBreak}
{doneTodo}
</>;
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
问题是您没有更新
todos
状态。您的状态在TodoTable
构造函数中定义为:但是您更新的状态是
todo
,这是之前未分配的新状态属性。在将
handleStatus
设为不可变之前,更改会起作用,因为您更改了实际的状态对象。然后在this.setState({ todo })
重新渲染组件后反映在 UI 中。handleStatus
中已有的todo
对象是todos
数组中已更改的项目。现在,使用更改设置todos
状态。编辑:这是对
handleStatus
的彻底更改。我添加了评论来澄清我做了什么。有很多方法可以不可变地更改数组(您也可以拼接
并通过索引查找,或映射
一个新数组),我在这里建议一种方法。The problem is that you do not update the
todos
state. Your state is defined inTodoTable
constructor as:But the state you update is
todo
, which is a new state property that wasn't assigned before.Before you made
handleStatus
immutable, the change worked because you changed the actual state object. Then it was reflected in the UI afterthis.setState({ todo })
re-rendered the component.todo
object that you already have inhandleStatus
is the item in thetodos
array that has changed. Now, set thetodos
state with the changes.Edit: here is a complete change in
handleStatus
. I added comments to clarify what I did. There are many ways to change an array immutably (you can alsosplice
and find by index, ormap
a new array), I suggest here one way.