reactjs - 我认为渲染工作两次
问题描述
我只是在学习 React,试图编写一个简单的 TODO 列表应用程序。当我尝试添加新任务时,会添加两个相同的任务。我尝试通过 console.log 元素进行调试,发现了一个问题。渲染工作两次,所以我的按钮两次向函数发送信息。有人可以指导我解决问题吗?这是代码。
import React from 'react';
class TaskInput extends React.Component {
constructor(props) {
super(props);
this.state = {
input: ''
};
}
addTask = () => {
const { input } = this.state;
if (input) {
this.props.addTask(input);
this.setState({ input: '' });
}
};
handleEnter = event => {
if (event.key === 'Enter') this.addTask();
};
inputChange = event => {
this.setState({ input: event.target.value });
};
render() {
const { input } = this.state;
console.log(this.state);
return (
<div className="task-input">
<input
type="text"
onKeyPress={this.handleEnter}
onChange={this.inputChange}
value={input}
></input>
<button onClick={this.addTask } >ADD</button>
</div>
);
}
}
export default TaskInput;
这是 App.js 代码:
import React from 'react';
import Task from './components/Task';
import TaskInput from './components/TaskInput';
class App extends React.Component {
constructor () {
super();
this.state = {
tasks: [
{id: 0, title: 'Create Todo-app', done: false},
{id: 1, title: 'Do smth else', done: true},
{id: 2, title: 'Do more things', done: false}
]
};
}
addTask = task => {
this.setState(state => {
let {tasks} = state;
console.log("state");
tasks.push({
id: tasks.length !==0 ? tasks.length : 0,
title: task,
done: false
});
return tasks;
});
}
doneTask = id => {
const index = this.state.tasks.map(task => task.id).indexOf(id);
this.setState(state => {
let {tasks} = state;
tasks[index].done = true;
return tasks;
});
};
deleteTask = id => {
const index = this.state.tasks.map(task => task.id).indexOf(id);
this.setState(state => {
let {tasks} = state;
delete tasks[index];
return tasks;
})
};
render() {
const { tasks } = this.state;
const activeTasks = tasks.filter(task => !task.done);
const doneTasks = tasks.filter(task => task.done)
return (
<div className = "App">
<h1 className="top">Active tasks: {activeTasks.length}</h1>
{[...activeTasks, ...doneTasks].map(task => (
<Task
doneTask={() => this.doneTask(task.id)}
deleteTask={() => this.deleteTask(task.id)}
task={task}
key={task.id}
></Task>))}
<TaskInput addTask={this.addTask}></TaskInput>
</div>
);
}
}
export default App;
解决方案
我认为您不小心直接修改了里面的状态addTask
。
该行let {tasks} = state;
正在创建对原始状态的引用,而不是新副本,然后您的推送直接修改状态。
使用扩展/扩展语法来获取数组的副本应该可以:
addTask = task => {
this.setState(state => {
const tasks = [ ...state.tasks ];
tasks.push({
id: tasks.length !==0 ? tasks.length : 0,
title: task,
done: false
});
return { tasks };
});
}
usinglet tasks = [ ...state.tasks ];
将创建一个新数组而不是引用,并防止直接修改状态。
您看到双重结果的原因是您通过推送有效地设置了状态,然后使用返回值再次设置它。
推荐阅读
- sparse-matrix - 使用 Eigen rankupdate
- mysql - 查找表中最常见的值 [SQL,MySQL]
- c - 二叉树的中序后继
- firebase - 从 Flutter 上的完整 url 获取 firebase 存储参考
- python - Python 套接字:使用 send() 和 recv() 时有关网络缓冲区的问题
- scala - 根据时间戳值连接 Dataframe 行
- sql - 在 pgadmin 4 中将 .tar 文件恢复到自定义模式的问题
- python - 使用 Python 仅将 HDF5 文件中的部分数据加载到内存中
- json - 你如何在 Swift 中解析递归 JSON?
- gitlab - 为 PostgreSQL RDS 实例安装 pg_trgm 扩展