当react组件状态改变时,将调用渲染方法。因此,对于任何状态更改,都可以在呈现方法体中执行操作。setState回调有特殊的用例吗?


当前回答

有时我们需要一个代码块,我们需要在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
     }
  });
}

enableModal布尔值在渲染函数的UI块中也是必需的,这就是为什么我在这里做了setState,否则,可以只检查条件一次,要么调用API set,要么不。

其他回答

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

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

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

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

非常糟糕的做法,因为渲染方法应该是纯的,这意味着不应该执行任何操作,状态更改,api调用,只是组合你的视图并返回它。应该只对某些事件执行操作。渲染不是一个事件,而是componentDidMount。

是的,有,因为setState以异步方式工作。这意味着在调用setState this之后。状态变量不会立即改变。因此,如果你想在一个状态变量上设置状态后立即执行一个操作,然后返回一个结果,回调将是有用的

考虑下面的例子

....
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" });
  }
},
....

上面的代码可能不能像预期的那样工作,因为在对其执行验证之前,标题变量可能没有发生变化。现在你可能会想,我们可以在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" });
  }
},
....

另一个例子是当状态发生变化时,您希望进行分派和操作。你会想要在回调中而不是在render()中做,因为它将在每次重新渲染发生时被调用,因此许多这样的场景是可能的,在那里你将需要回调。

另一种情况是API调用

当你需要基于特定的状态变化进行API调用时,可能会出现这种情况,如果你在渲染方法中这样做,它将在每次渲染onState变化时被调用,或者因为传递给子组件的一些道具发生了变化。

在这种情况下,您需要使用setState回调将更新后的状态值传递给API调用

....
changeTitle: function (event) {
  this.setState({ title: event.target.value }, () => this.APICallFunction());
},
APICallFunction: function () {
  // Call API with the updated value
}
....
this.setState({
    name:'value' 
},() => {
    console.log(this.state.name);
});

有时我们需要一个代码块,我们需要在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
     }
  });
}

enableModal布尔值在渲染函数的UI块中也是必需的,这就是为什么我在这里做了setState,否则,可以只检查条件一次,要么调用API set,要么不。

考虑setState调用

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

IDEA

setState可以在async函数中调用

So you cannot rely on this. If the above call was made inside a async function this will refer to state of component at that point of time but we expected this to refer to property inside state at time setState calling or beginning of async task. And as task was async call thus that property may have changed in time being. Thus it is unreliable to use this keyword to refer to some property of state thus we use callback function whose arguments are previousState and props which means when async task was done and it was time to update state using setState call prevState will refer to state now when setState has not started yet. Ensuring reliability that nextState would not be corrupted.

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

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

setState具有回调功能的正确代码:

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

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

我已经试着用CODE - PEN来解释它