尽管React很受欢迎,但它最大的缺点之一是它的组件会过度地重新渲染。在开发React应用程序时,你可能已经注意到,状态更新在被改变后并不能立即反映新的值。React状态是一个普通的JavaScript对象,持有影响渲染输出的信息。
当建立你的项目时,如果你打算在将来改变React组件的任何属性,你应该把属性存储在一个状态中。该状态在mount ,开始时有一个初始的默认值,后来由于用户的操作而被改变。每个React组件都在内部管理自己的状态。
在这篇文章中,我们将探讨React不立即更新状态的原因。我们将通过一个例子,阐明当你需要对类和函数组件的新状态进行修改时,你应该做什么。让我们开始吧!
React如何执行状态更新
为了更新React组件中的状态,我们将分别使用this.setState 函数或由React.useState() Hook在类和函数组件中返回的updater函数。
React中的状态更新是异步的;当请求更新时,并不保证会立即进行更新。更新函数对组件状态的变化进行排队,但React可能会延迟这些变化,一次就更新几个组件。
例如,考虑下面的代码。
//React
const handleClick = () => {
setName("Amaka")
setAge(20)
setAddress("No 3 Rodeo drive")
}
在上面的代码片段中,有三个不同的调用来更新和重新渲染组件。在大多数情况下,一个接一个地调用更新器函数,并在每次调用后重新渲染父组件和子组件,效率会很低。出于这个原因,React对状态更新进行批处理。
无论handleClick 事件处理程序中有多少个setState() 调用,它们都只会在事件结束时产生一次重新渲染,这对于在大型应用中保持良好的性能至关重要。更新请求的顺序总是被尊重的;React总是先处理第一个更新请求。
现在我们已经确定,为了批处理更新请求而延迟调和是有好处的,也有一些时候,你需要等待更新,对更新的值做一些处理。在下一节,我们将看到如何做到这一点。
用类组件进行操作
setState() 回调
setState() 的第二个参数是一个可选的回调函数。一旦setState() ,该参数将被执行,组件将被重新渲染。回调函数保证在状态更新应用后运行。
//React
handleSearch = (e) => {
this.setState({
searchTerm: e.target.value
},() => {
// Do an API call with this.state.searchTerm
});
}
componentDidUpdate
componentDidUpdate 函数会在状态更新发生后立即被调用。为了避免无限循环,你应该始终使用一个条件语句来确保之前的状态和当前的状态不一样。
//React
componentDidUpdate(prevProps, prevState) {
if (prevState.count !== this.state.count) {
// Do something here
}
}
用函数组件进行操作
useEffect() 钩子
当状态被更新时,你可以在useEffect Hook中执行副作用。状态变量可以作为一个依赖项被添加到这个Hook中,使其在状态值改变时运行。你可以让useEffect Hook监听状态的变化。
//React
import React,{useState, useEffect} from 'react';
const App = () => {
const [count, setCount] = useState(1);
useEffect(() => {
if (count > 5) {
console.log('Count is more that 5');
} else {
console.log('Count is less that 5');
}
}, [count]);
const handleClick = () => {
setCount(count + 1);
};
return (
<div>
<p>{count}</p>
<button onClick={handleClick}>
add
</button>
</div>
);
};
export default App;
useEffect Hook中的回调函数只在作为依赖关系提供的状态变量变化时运行。
总结
在React中,每次状态更新都会导致被更新的组件重新渲染。因为重新渲染是一个昂贵的操作,同步进行状态更新会导致严重的性能问题,例如,增加加载时间或导致你的应用程序崩溃。通过批处理状态更新,React避免了不必要的重新渲染,提高了整体性能。我希望你喜欢这篇文章!
The postWhy React doesn't update state immediatelyappeared first onLogRocket Blog.