React setState 不立即更新

IT技术 reactjs redux state setstate
2021-03-30 23:39:15

我正在开发一个待办事项应用程序。这是违规代码的一个非常简化的版本。我有一个复选框:

 <p><input type="checkbox"  name="area" checked={this.state.Pencil}   onChange={this.checkPencil}/> Writing Item </p>

这是调用复选框的函数:

checkPencil(){
   this.setState({
      pencil:!this.state.pencil,
  }); 
  this.props.updateItem(this.state);
}

updateItem 是一个映射到分派到 redux 的函数

function mapDispatchToProps(dispatch){
  return bindActionCreators({ updateItem}, dispatch);
}

我的问题是,当我调用 updateItem 操作和 console.log 状态时,它总是落后 1 步。如果复选框未选中且不为真,我仍然会得到传递给 updateItem 函数的真状态。我是否需要调用另一个函数来强制更新状态?

6个回答

您应该调用第二个函数作为 setState 的回调,因为 setState 是异步发生的。就像是:

this.setState({pencil:!this.state.pencil}, myFunction)

但是,在您的情况下,由于您希望使用参数调用该函数,因此您将不得不更有创意,并且可能创建自己的函数来调用 props 中的函数:

myFunction = () => {
  this.props.updateItem(this.state)
}

将它们组合在一起,它应该可以工作。

解决方案描述性不够。
2021-05-22 23:39:15
在箭头函数中,this绑定到封闭范围,所以我很确定你有倒退。
2021-05-26 23:39:15

setState()由于各种原因(主要是性能),React 中的调用是异步的。在幕后,React 会将多次调用批处理setState()为单个状态突变,然后重新渲染组件一次,而不是为每个状态更改重新渲染。

幸运的是,解决方案相当简单——setState接受一个回调参数:

checkPencil: () => {
   this.setState(previousState => ({
      pencil: !previousState.pencil,
   }), () => {
      this.props.updateItem(this.state);
   });
}

当您使用当前状态的属性更新状态时,React 文档建议您使用 的函数调用版本setState而不是对象。

所以setState((state, props) => {...})代替setState(object).

原因是这setState更多是要求状态改变而不是立即改变。React 批量处理那些setState性能改进的调用。

这意味着您正在检查的状态属性可能不稳定。这是一个需要注意的潜在陷阱。

有关更多信息,请参阅此处的文档:https : //facebook.github.io/react/docs/react-component.html#setstate


为了回答你的问题,我会这样做。

checkPencil(){
    this.setState((prevState) => {
        return {
            pencil: !prevState.pencil
        };
    }, () => {
        this.props.updateItem(this.state)
    });
}

这是因为它是异步发生的,所以意味着在那个时候可能还没有更新......

根据 React v.16 文档,您需要使用setState()接受函数而不是对象的第二种形式

状态更新可能是异步的

React 可以将多个 setState() 调用批处理为单个更新以提高性能。

因为 this.props 和 this.state 可能会异步更新,所以你不应该依赖它们的值来计算下一个状态。

例如,此代码可能无法更新计数器:

// Wrong
this.setState({
  counter: this.state.counter + this.props.increment,
});

要修复它,请使用 setState() 的第二种形式,它接受一个函数而不是一个对象。该函数将接收先前的状态作为第一个参数,并将应用更新时的 props 作为第二个参数:

// Correct
this.setState((prevState, props) => ({
  counter: prevState.counter + props.increment
}));

在 Ben Hare 的回答中,如果有人想使用 React Hooks 实现相同的目标,我在下面添加了示例代码。

import React, { useState, useEffect } from "react"

let [myArr, setMyArr] = useState([1, 2, 3, 4]) // the state on update of which we want to call some function

const someAction = () => {
  let arr = [...myArr]
  arr.push(5) // perform State update
  setMyArr(arr) // set new state
}

useEffect(() => { // this hook will get called everytime when myArr has changed
// perform some action which will get fired everytime when myArr gets updated
   console.log('Updated State', myArr)
}, [myArr])
这是我要建议的首选方式。
2021-06-04 23:39:15