何时使用 React setState 回调

IT技术 reactjs callback setstate
2021-04-20 23:23:52

当 React 组件状态发生变化时,会调用 render 方法。因此,对于任何状态更改,都可以在渲染方法主体中执行操作。那么 setState 回调有特定的用例吗?

5个回答

是的,因为setStateasynchronous某种程度上起作用打完电话后这意味着setStatethis.state变量不会立即改变。因此,如果您想在状态变量上设置状态后立即执行操作然后返回结果,回调将很有用

考虑下面的例子

....
changeTitle: function changeTitle (event) {
  this.setState({ title: event.target.value });
  this.validateTitle();
},
validateTitle: function validateTitle () {
  if (this.state.title.length === 0) {
    this.setState({ titleError: "Title can't be blank" });
  }
},
....

上面的代码可能无法按预期工作,因为title在对其执行验证之前变量可能没有发生变异。现在您可能想知道我们可以在render()函数本身中执行验证,但如果我们可以在 changeTitle 函数本身中处理它会更好更干净,因为这将使您的代码更有条理和易于理解

在这种情况下回调很有用

....
changeTitle: function changeTitle (event) {
  this.setState({ title: event.target.value }, function() {
    this.validateTitle();
  });

},
validateTitle: function validateTitle () {
  if (this.state.title.length === 0) {
    this.setState({ titleError: "Title can't be blank" });
  }
},
....

另一个例子是当你想要dispatch和行动时状态改变。您将希望在回调中执行此操作,而不是在render()每次重新渲染发生时都会调用它,因此在您需要回调的情况下,可能会出现许多此类情况。

另一种情况是 API Call

当您需要根据特定状态更改进行 API 调用时可能会出现这种情况,如果您在渲染方法中执行此操作,它将在每次渲染onState更改时调用,或者因为某些 Prop 传递给已Child Component更改的。

在这种情况下,您可能希望使用 asetState callback将更新的状态值传递给 API 调用

....
changeTitle: function (event) {
  this.setState({ title: event.target.value }, () => this.APICallFunction());
},
APICallFunction: function () {
  // Call API with the updated value
}
....
@SahilJain Validation 是正确的示例,您不会希望在 render() 函数中处理它,因为每次您在 render() 中进行任何更改时都会调用它,您只想在仅输入更改时调用它,因此在函数本身
2021-05-22 23:23:52
React 禁止在渲染期间更改状态..因此将验证放入回调中是正确的。
2021-05-30 23:23:52
第一个用例可能不是一个好主意。setState 回调在重新渲染后触发,因此您无缘无故地导致了双重渲染。这正是函数参数(更新程序)的目的。您只需运行即可setState(state => state.title.length ? { titleError: "Title can't be blank" } : null),更改将叠加。不需要双重渲染。
2021-06-07 23:23:52
if (this.title.length === 0) {应该是this.state.title.length吧?
2021-06-14 23:23:52
我知道它本质上是异步的。我的问题是有什么特定的东西只有 setState 回调可以用于渲染方法主体可能不支持的东西(除了让我们说更好的代码可读性之外的东西。)
2021-06-17 23:23:52
this.setState({
    name:'value' 
},() => {
    console.log(this.state.name);
});
感谢您提供此代码片段,它可能会提供一些有限的即时帮助。一个正确的解释将通过展示为什么这是一个很好的问题解决方案来极大地提高其长期value,并且会使它对未来有其他类似问题的读者更有用。编辑您的答案以添加一些解释,包括您所做的假设。
2021-05-23 23:23:52
如果您想设置多个状态属性,例如姓名、名字等,该怎么办?
2021-05-28 23:23:52
当你想在状态改变后调用一个函数时,你可以使用该方法。
2021-06-13 23:23:52

我想到的 1. 用例是一个api调用,它不应该进入渲染,因为它将运行each状态更改。并且 API 调用应该只在特殊的状态变化时执行,而不是在每次渲染时执行。

changeSearchParams = (params) => {
  this.setState({ params }, this.performSearch)
} 

performSearch = () => {
  API.search(this.state.params, (result) => {
    this.setState({ result })
  });
}

因此,对于任何状态更改,都可以在渲染方法主体中执行操作。

非常糟糕的做法,因为render-method 应该是纯的,这意味着不应该执行任何操作、状态更改、api 调用,只需组合您的视图并返回它。应仅对某些事件执行操作。Render 不是事件,而是componentDidMount例如。

考虑 setState 调用

this.setState({ counter: this.state.counter + 1 })

主意

可以在异步函数中调用 setState

所以你不能依赖this. 如果上述调用是在异步函数内部进行的,this则将引用该时间点的组件状态,但我们预计这将引用 setState 调用或异步任务开始时的状态内部属性。由于任务是异步调用,因此该属性可能会及时更改。因此,使用this关键字来引用状态的某些属性是不可靠的,因此我们使用参数为 previousState 和 props 的回调函数,这意味着当异步任务完成并且是时候使用 setState 更新状态调用 prevState 将引用 state now 当 setState还没有开始。确保 nextState 不会被破坏的可靠性。

错误的代码:会导致数据损坏

this.setState(
   {counter:this.state.counter+1}
 );

具有回调函数的 setState 的正确代码:

 this.setState(
       (prevState,props)=>{
           return {counter:prevState.counter+1};
        }
    );

因此,每当我们需要根据属性所拥有的值将当前状态更新到下一个状态时,并且所有这些都以异步方式发生,使用 setState 作为回调函数是个好主意。

我试图在 codepen 中解释它 CODE PEN

有时我们需要一个代码块,我们需要在 setState 之后立即执行一些操作,我们确定状态正在更新。这就是 setState 回调发挥作用的地方

例如,有一个场景,我需要为 20 个客户中的 2 个客户启用模式,对于我们启用它的客户,有一组时间进行 API 调用,所以它看起来像这样

async componentDidMount() {
  const appConfig = getCustomerConfig();
  this.setState({enableModal: appConfig?.enableFeatures?.paymentModal }, async 
   ()=>{
     if(this.state.enableModal){
       //make some API call for data needed in poput
     }
  });
}

渲染函数中的 UI 块中也需要 enableModal 布尔值,这就是我在这里设置 setState 的原因,否则,可能只检查一次条件并调用 API 集或不调用。