React中狀態(tài)設(shè)置this.setState()的實現(xiàn)
React 中的狀態(tài)設(shè)置,即 setState。這是一個核心概念,但它在 類組件和 函數(shù)組件(使用 Hook) 中有不同的寫法和行為。
我會分兩部分來解釋。
第一部分:類組件中的setState
在類組件中,狀態(tài)是一個叫 this.state 的對象,而更新狀態(tài)的方法是 this.setState()。
1. 基本用法
setState 用于更新組件的狀態(tài)對象,并通知 React 需要重新渲染。
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
increment() {
// 傳入一個新的對象來更新狀態(tài)
this.setState({ count: this.state.count + 1 });
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={() => this.increment()}>
Click me
</button>
</div>
);
}
}
2. 關(guān)鍵特性:異步與批處理
setState 是異步的!
當(dāng)你調(diào)用 setState 時,React 不會立即更新組件。它會將多個 setState 調(diào)用合并在一起(批處理 Batched Updates),然后進行一次更新以提高性能。
這意味著你不能在調(diào)用 setState 后立刻依賴 this.state 來獲取最新值。
// ? 錯誤的做法
increment() {
this.setState({ count: this.state.count + 1 });
console.log(this.state.count); // 這里打印的仍然是舊的值,不是 +1 后的值
}
3. 如何依賴前一個狀態(tài)?使用函數(shù)形式
為了解決異步問題并確保你基于最新的狀態(tài)進行更新,setState 可以接受一個函數(shù)作為參數(shù),而不是一個對象。
這個函數(shù)會接收先前的狀態(tài)(prevState) 作為第一個參數(shù)。
increment() {
this.setState((prevState) => {
return { count: prevState.count + 1 }; // 基于之前的狀態(tài)計算新狀態(tài)
});
}
這種形式在需要進行多次連續(xù)狀態(tài)更新時尤其重要,因為它能保證每次更新都基于最新且正確的前一個狀態(tài)。
4. 第二個參數(shù):回調(diào)函數(shù)
setState 的第二個參數(shù)是一個可選的回調(diào)函數(shù),它會在狀態(tài)更新完成并且組件重新渲染后執(zhí)行。你可以在這里執(zhí)行一些依賴于新狀態(tài) DOM 的操作。
increment() {
this.setState(
(prevState) => ({ count: prevState.count + 1 }),
() => {
console.log('狀態(tài)已更新,當(dāng)前count是:', this.state.count); // 這里可以拿到最新值
// 可以在這里操作DOM,比如根據(jù)新的狀態(tài)設(shè)置焦點等
}
);
}
第二部分:函數(shù)組件中的setState(使用useStateHook)
在函數(shù)組件中,我們使用 useState Hook 來管理狀態(tài)。它返回一個狀態(tài)值和一個用于更新該狀態(tài)的函數(shù)(通常命名為 setXxx)。
1. 基本用法
import { useState } from 'react';
function Counter() {
// useState 返回一個數(shù)組: [當(dāng)前狀態(tài)值, 更新狀態(tài)的函數(shù)]
const [count, setCount] = useState(0);
function increment() {
// 直接傳入新的值
setCount(count + 1);
}
return (
<div>
<p>You clicked {count} times</p>
<button onClick={increment}>
Click me
</button>
</div>
);
}
2. 同樣具有異步和批處理特性
函數(shù)組件中的 setCount 也是異步的,并且也會被 React 批量處理。你不能在調(diào)用 setCount 后立刻讀取 count 的值,因為它還沒有被更新。
// ? 錯誤的做法
function increment() {
setCount(count + 1);
console.log(count); // 仍然是舊值
}
3. 如何依賴前一個狀態(tài)?同樣使用函數(shù)形式
與類組件類似,更新函數(shù)(如 setCount)也可以接受一個函數(shù)。這個函數(shù)接收先前的狀態(tài)值作為其唯一參數(shù)。
function increment() {
setCount((prevCount) => prevCount + 1);
}
這是推薦的做法,尤其是在事件循環(huán)中可能會多次更新同一個狀態(tài)時,它能保證你總是在最新的狀態(tài)基礎(chǔ)上進行更新。
4. 與類組件setState的重大區(qū)別
| 特性 | 類組件 this.setState | 函數(shù)組件 setXxx (Hook) |
|---|---|---|
| 更新機制 | 合并更新:傳入的對象會與舊 state 淺合并。 | 替換更新:直接用新值替換舊狀態(tài)。不會自動合并對象! |
| 示例 | this.setState({ user }); 只會更新 state.user,不影響 state.posts。 | setUser(newUser) 會直接用 newUser替換掉整個 user 狀態(tài)。 |
函數(shù)組件中更新對象狀態(tài)的正確做法:
因為你不能直接修改狀態(tài),必須創(chuàng)建一個新對象。
const [user, setUser] = useState({ name: 'Alice', age: 25 });
function updateName(newName) {
// ? 錯誤:直接修改原對象
// user.name = newName;
// setUser(user); // 不會觸發(fā)重新渲染,因為引用沒變
// ? 正確:展開運算符創(chuàng)建新對象
setUser({
...user, // 拷貝所有舊屬性
name: newName // 用新值覆蓋其中的name屬性
});
}
總結(jié)與最佳實踐
- 都是異步的:無論類組件還是函數(shù)組件,
setState都是異步操作,不要指望調(diào)用后能立刻拿到新值。 - 使用函數(shù)形式更新:當(dāng)你新的狀態(tài)依賴于舊的狀態(tài)時(如計數(shù)器、列表追加等),務(wù)必使用
setXxx(prevState => newState)的函數(shù)形式。這是最安全、最可靠的做法。 - 理解更新差異:
- 類組件:合并更新。
- 函數(shù)組件:替換更新。更新對象時記得使用展開運算符
...或Object.assign()來創(chuàng)建一個新對象。
- 副作用操作:在類組件中,使用
setState(updater, callback)的第二個回調(diào)參數(shù)。在函數(shù)組件中,使用useEffectHook 來響應(yīng)狀態(tài)的變化。useEffect(() => { ... }, [count]);
到此這篇關(guān)于React中狀態(tài)設(shè)置this.setState()的文章就介紹到這了,更多相關(guān)React 狀態(tài)設(shè)置this.setState()內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
React路由監(jiān)聽/跳轉(zhuǎn)/守衛(wèi)的完整指南
React Router 是 React 單頁應(yīng)用的核心路由庫,除了基礎(chǔ)的路由配置,日常開發(fā)中還會高頻用到路由監(jiān)聽、編程式跳轉(zhuǎn)、路由守衛(wèi)等進階功能,本文從實戰(zhàn)角度拆解這三大核心能力,需要的朋友可以參考下2026-03-03
react中hooks使用useState的更新不觸發(fā)dom更新問題及解決
這篇文章主要介紹了react中hooks使用useState的更新不觸發(fā)dom更新問題及解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-01-01
基于react hooks,zarm組件庫配置開發(fā)h5表單頁面的實例代碼
這篇文章主要介紹了基于react hooks,zarm組件庫配置開發(fā)h5表單頁面,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-04-04
react中useEffect函數(shù)的詳細用法(最新推薦)
useEffect是React中的一個Hook,用于在函數(shù)組件中處理副作用(如數(shù)據(jù)獲取、訂閱、手動更改 DOM 等),useEffect屬于組件的生命周期方法,下面通過本文給大家分享react中useEffect函數(shù)的詳細用法,感興趣的朋友跟隨小編一起看看吧2024-06-06
React創(chuàng)建組件的三種方式及其區(qū)別
本文主要介紹了React創(chuàng)建組件的三種方式及其區(qū)別,具有一定的參考價值,下面跟著小編一起來看下吧2017-01-01
React Native AsyncStorage本地存儲工具類
這篇文章主要為大家分享了React Native AsyncStorage本地存儲工具類,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-10-10

