何时使用React setState回调

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

426889 次浏览

是的,有,因为setStateasynchronous的方式工作。这意味着调用setState后,this.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变化时被调用,或者因为传递给Child Component的某些Prop发生了变化。

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

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

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

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


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

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

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

考虑setState调用

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

的想法

setState可以在async函数中调用

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

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

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

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

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

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

我已经试着用代码解释了 代码的钢笔

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,要么不。