Javascript setState未正确更新状态
对不起,我真的错过了React中子组件的Javascript setState未正确更新状态,javascript,reactjs,Javascript,Reactjs,对不起,我真的错过了React中子组件的props中的state传输 我已经实现了一个包含3个组件的todo列表版本 有一个Form组件和一个ListTodo组件。该状态仅存储在App组件中 import React, {Component} from 'react'; import './App.css'; class App extends Component { constructor(props) { super(props); this.st
props
中的state
传输
我已经实现了一个包含3个组件的todo列表版本
有一个Form
组件和一个ListTodo
组件。该状态仅存储在App
组件中
import React, {Component} from 'react';
import './App.css';
class App extends Component {
constructor(props) {
super(props);
this.state = {
tasks: ["un truc", "autre truc"]
};
this.addTask = this.addTask.bind(this);
}
addTask(task) {
this.setState({
tasks: this.state.tasks.push(task)
})
}
render() {
return (
<div className="App">
<Form onTaskAdded={ this.addTask }></Form>
<ListTodo tasks={ this.state.tasks }></ListTodo>
</div>
);
}
}
class Form extends Component {
constructor(props) {
super(props);
this.state = {
task: ""
}
this.handleChange = this.handleChange.bind(this);
this.addTask = this.addTask.bind(this);
}
handleChange(event) {
this.setState({
task: event.target.value
});
}
addTask(event) {
this.props.onTaskAdded(this.state.task);
event.preventDefault();
}
render() {
return (
<form onSubmit={ this.addTask }>
<input placeholder="À faire" onChange={ this.handleChange }></input>
<input type="submit"></input>
</form>
)
}
}
class ListTodo extends Component {
render() {
const tasks = this.props.tasks.map((t, i) => (
<li key={i}>{t}</li>
))
return (
<ul>{tasks}</ul>
)
}
}
export default App;
import React,{Component}来自'React';
导入“/App.css”;
类应用程序扩展组件{
建造师(道具){
超级(道具);
此.state={
任务:[“休战”、“休战”]
};
this.addTask=this.addTask.bind(this);
}
添加任务(任务){
这是我的国家({
任务:this.state.tasks.push(任务)
})
}
render(){
返回(
);
}
}
类形式扩展组件{
建造师(道具){
超级(道具);
此.state={
任务:“
}
this.handleChange=this.handleChange.bind(this);
this.addTask=this.addTask.bind(this);
}
手变(活动){
这是我的国家({
任务:event.target.value
});
}
添加任务(事件){
this.props.onTaskAdded(this.state.task);
event.preventDefault();
}
render(){
返回(
)
}
}
类ListTodo扩展组件{
render(){
const tasks=this.props.tasks.map((t,i)=>(
{t}
))
返回(
{tasks}
)
}
}
导出默认应用程序;
开始时显示良好,因此列表TODO
可以查看道具任务
。但是在提交表单之后,我在ListTodo.render上得到一个错误:
TypeError:this.props.tasks.map不是函数
当我在console.log中记录this.props.tasks
时,我不获取数组,而是获取数组的长度
你知道为什么吗
编辑:
谢谢你们的回答,伙计们,你们说得对。我错过了Array.push的行为
但反应似乎仍然很奇怪。如果我让错误的代码
this.setState({
任务:this.state.tasks.push(任务)
})
然后一个console.log(JSON.stringify(this.state))
显示:
{“任务”:[“不停战”、“自动停战”、“不停战”]}
无法信任控制台非常令人不安。根据以下内容记录…:
push()方法将一个或多个元素添加到数组的末尾,然后
返回数组的新长度
从不返回结果数组,它返回数字,因此在添加第一个任务后,this.state.tasks
将成为一个数字,并且在您尝试运行map on number时抛出错误
你在这里犯了错误:
addTask(task) {
this.setState({
tasks: this.state.tasks.push(task)
})
}
这样写:
addTask(task) {
this.setState( prevState => ({
tasks: [...prevState.tasks, task]
}))
}
这里的另一个重要内容是,新状态将取决于以前的状态值,因此,不要在setState中使用this.state
,而是使用updater函数
关于编辑部件的说明:
两件重要的事情正在那里发生:
1-setState是异步的,因此在setState之后,我们可以期望更新的状态值
有关的更多详细信息,请查看此项
2-Array.push总是通过将项推入原始数组来改变原始数组,因此您可以通过this.state.tasks.push()直接改变状态值
有关设置状态的更多详细信息,请查看
检查中的扩展运算符(…)
检查此代码段:
设a=[1,2,3,4];
设b=a.推(5)//这将是一个数字
log('a=',a);
log('b=',b)代码>问题在于如何在应用程序状态下添加任务
addTask(task) {
this.setState({
tasks: this.state.tasks.push(task)
})
}
请参见,添加元素后数组的。你真正想要的是
此外,多亏了@t-j-crowder指针,正如@mayank shukla所报道的,你应该使用不同的方法来改变你的状态:
addTask(task) {
this.setState(function (state) {
return {
tasks: state.tasks.concat([ task ])
}
});
}
或者使用ES2015箭头、对象分解和阵列扩展:
addTask(task) {
this.setState(({ tasks }) => ({
tasks: [ ...tasks, task ]
}));
}
由于Component.prototype.setState
可以是异步的,因此将函数传递给它将保证新状态值取决于右侧的当前先前值
这意味着,如果两个或多个setState
调用相继发生,您可以通过应用第二个来确保第一个调用的结果将被保留。正如其他答案所述,Arraypush
方法不会返回数组。为了补充上面的答案,如果您正在使用ES6,那么使用spread操作符(您可以阅读更多有关它的信息)是一种很好且优雅的方法
它本质上与使用concat
方法相同,但我认为它具有更好的可读性。问题在于数组。push返回数组中的元素数,而不是更新的数组
addTask(task) {
this.setState({
tasks: this.state.tasks.push(task)
})
}
要解决此问题,您可以推送到state.tasks,然后稍后使用它设置state:
addTask(task) {
this.state.tasks.push(task);
this.setState({
tasks: this.state.tasks
})
}
通过这种方式,您可以将state.task设置为更新后的数组。您可能会说为什么,甚至可能会参考文档中有关此内容的内容。。。特别是你改变了两件事(都很重要),你是对的。我错过了Array.push的行为。但是,如果我让this.setState({tasks:this.state.tasks.push(task)})
,那么console.log(JSON.stringify(this.state))
会显示:{“tasks”:[“untruc”,“autre truc”,“aze”}
17:12:52.634这里有两个重要的东西,1-setState是异步的,因此在setState之后,我们不能期望更新的状态值,2-您正在直接改变状态值数组。push将把元素推入主数组。有关setState异步行为的更多详细信息,请检查。感谢@MayankShukla!用你的ans
addTask(task) {
this.setState({
tasks: this.state.tasks.push(task)
})
}
addTask(task) {
this.state.tasks.push(task);
this.setState({
tasks: this.state.tasks
})
}