【React學習】React中的setState方法

1. setState概述

setState 是React框架中,用于更新組件狀態的方法。
setState 方法由React組件繼承自 React.Component 類的一部分。通過調用 setState,可以告訴 React要更新組件的狀態,并觸發組件的重新渲染。

this.setState(newState, callback);

newState 是一個對象,它包含了需要更新的狀態屬性和值。它將合并到組件的當前狀態中。
callback 是一個回調函數,它在 setState 更新狀態完成之后被調用。

2. setState為何使用不可變值

  • 什么是 不可變值

React框架中的“不可變值”的概念,通常指的是在編寫React組件時,盡量避免直接修改數據,而是創建新的數據副本。

  • setState為何使用不可變值?

在React中,組件的狀態(state)應該保持不變。通過使用 setState 方法更新狀態時,React會合并現有狀態和新狀態,而不是直接修改狀態。 這確保 React 可以正確地追蹤狀態的變化并進行必要的更新。

同時,直接修改數據可能會引發意外的副作用,尤其是在多個組件之間共享數據時。通過使用不可變值,可以減少出現這種問題的可能性。

常用的處理不可變值的工具包括 Object.assign、數組的 concatslice 等方法。對數組或者對象使用slice()方法,可以生成該數組或對象的副本,類似于深拷貝。

const list5Copy = this.state.list5.slice()
list5Copy.splice(2, 0, 'a') // 中間插入/刪除this.setState({list1: this.state.list1.concat(100), // 追加list2: [...this.state.list2, 100], // 追加list3: this.state.list3.slice(0, 3), // 截取list4: this.state.list4.filter(item => item > 100), // 篩選list5: list5Copy // 其他操作
})

3. setState可能是異步的

setState是一個異步方法。這意味著React可能會對多個 setState 調用進行批處理,然后一次性更新組件的狀態,而不是每次調用都立即更新。

然而,setTimeout 函數中的 setState 是同步的。在自定義的DOM事件中,setState也是同步的。

state要在構造函數中定義

constructor(props){this.state = {count: 0}
}

因為 setState 是異步的,因此在 setState 方法執行完后打印狀態,是拿不到更新后的值,只能拿到當前狀態的值。

this.setState({count: this.state.count + 1; 
})
console.log(this.state.count) //打印結果為 0

如果想要拿到最新的狀態,需要在setState中,寫一個回調函數。此時count的結果為1

this.setState({count: this.state.count + 1},() => {console.log(this.state.count)}
)
  • setTimeout 中的 setState 是同步的。此時打印出來的count結果就是1
setTimeout(()=>{this.setState({count: this.state.count + 1})console.log(this.state.count)  // 打印結果為1
}, 0)
  • 在自定義的DOM事件中,setState也是同步的。
bodyClickHandler = () => {this.setState({count: this.state.count + 1})console.log(this.state.count)   // 打印結果為1
}componentDidMount(){document.body.addEventListener('click', this.bodyClickHandler)
}

4. setState何時合并state

  • setState是異步更新的話,傳入的參數是一個對象,那么多次更新同一個狀態只會執行1次。
constructor(props){this.state = {count: 0}
}this.setState({count: this.state.count + 1
})
this.setState({count: this.state.count + 1
})
this.setState({count: this.state.count + 1
})
console.log(this.state.count) // 打印結果為 1

由于 setState 是異步的,React 會將這些更新一起批處理,然后應用它們。這意味著所有三個 setState 調用可能幾乎同時執行,使用初始值 this.state.count,導致增加只有 1 而不是 3。

上述代碼的思想類似于

Object.assign({count: 1}, {count: 1}, {count: 1}) // 執行結果為 {count: 1}
  • 為了防止這種情況發生,可以在setState中傳入更新函數(updater function),它接受先前的狀態并返回更新后的狀態。這能夠確保使用的是最新的狀態。
constructor(props){this.state = {count: 0}
}this.setState((prevState) => ({count: prevState.count + 1
}));
this.setState((prevState) => ({count: prevState.count + 1
}));
this.setState((prevState) => ({count: prevState.count + 1
}));console.log(this.state.count) // 打印結果為 3

5. React18中的setState

  • 當React的版本小于等于17時,在組件中直接使用setState更新狀態,是批處理的(即異步更新且合并相同狀態)。在setTimeout方法和自定義DOM事件中,使用setState方法更新狀態是同步的,不是批處理的。
  • 然而,在React18版本中,無論是在組件中直接更新狀態還是在自定義DOM事件和setTiemout方法中更新,都是自動批處理(Automatic Batching)。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/43306.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/43306.shtml
英文地址,請注明出處:http://en.pswp.cn/news/43306.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C語言中常見的一些語法概念和功能

常用代碼: 程序入口:int main() 函數用于定義程序的入口點。 輸出:使用 printf() 函數可以在控制臺打印輸出。 輸入:使用 scanf() 函數可以接收用戶的輸入。 條件判斷:使用 if-else 語句可以根據條件執行不同的代碼…

【力扣每日一題】2023.8.15 字符中的查找與替換

目錄 題目: 示例: 分析: 代碼: 題目: 示例: 分析: 題目很長,簡而言之就是檢查字符串中對應索引的位置是否有特定的字符串,如果有,那么替換,返…

Ceph如何操作底層對象數據

1.基本原理介紹 1.1 ceph中的對象(object) 在Ceph存儲中,一切數據最終都會以對象(Object)的形式存儲在硬盤(OSD)上,每個的Object默認大小為4M。 通過rados命令,可以查看一個存儲池中的所有object信息,例如…

Optional的基礎運用

Optional的基礎運用 簡介代碼示例 簡介 代碼示例 package org.example;import org.junit.Test;import java.util.Optional;public class OptionalTest {Testpublic void advance() {String str "hello";str null;// of(T t):封裝數據t生成Optional對象&#xff0c…

【筆試題心得】關于正則的一些整理

本文部分內容摘抄整理自 正則表達式 – 教程 | 菜鳥教程 在筆試的過程中,也常常會對正則表達式進行考察,這里對正則表達式的常見用法,做一個學習和總結。 正則表達式的模式可以包括以下內容: 字面值字符:例如字母、數…

數據結構:堆的實現

1.堆的概念 如果有一個關鍵碼的集合 K { k1 &#xff0c;k2 &#xff0c;k3 &#xff0c;…&#xff0c;kn }&#xff0c;把它的所有元素按完全二叉樹的順序存儲方式存儲在一個一維數組中&#xff0c;并且 k(i) < k(i*21) 和 k(i) < k(i*22)&#xff0c; i 0 &#xff…

MongoDB增刪改查操作

數據庫操作&#xff1a; 在MongoDB中&#xff0c;文檔集合存在數據庫中。 要選擇使用的數據庫&#xff0c;請在mongo shell程序中發出 use <db> 語句 // 查看有哪些數據庫 show dbs;// 如果數據庫不存在&#xff0c;則創建并切換到該數據庫&#xff0c;存在則直接切換到…

分布式消息中間件

消息中間件是Java開發消息隊列的一種中間件產品。中間件類似windows編程開發中的插件。工具插件在軟件工具中是中間插件。插件也是應用程序。消息的分發過程包裝之后是chatlog 系統或者是手機短信。系統與系統之間的通信通過消息的發送和接收。堆積頻繁過多的系統通知消息需要進…

C++之模板進階

模板進階 非類型模板參數模板的特化概念函數模板特化類模板特化全特化偏特化 模板分離編譯什么是分離編譯模板的分離編譯解決方法 模板總結 非類型模板參數 模板參數分兩種&#xff1a;類型形參與非類型形參。 類型形參&#xff1a;出現在模板參數列表中&#xff0c;跟在class…

docker安裝consul

1、下載consul鏡像 docker pull consul2、啟動consul docker run -d --restartalways --name consul -p 8500:8500 consul agent -server -bootstrap-expect1 -ui -bind0.0.0.0 -client0.0.0.03、查看consul日志 docker logs consul4、檢驗是否安裝成功

drawio----輸出pdf為圖片大小無空白(圖片插入論文)

自己在寫論文插入圖片時為了讓論文圖片放大不模糊&#xff0c;啥方法都試了&#xff0c;最后摸索出來這個。 自己手動畫圖的時候導出pdf總會出現自己的圖片很小&#xff0c;pdf的白邊很大如下如所示&#xff0c;插入論文的時候后雖然放大不會模糊&#xff0c;但是白邊很大會顯…

【數據結構OJ題】用隊列實現棧

原題鏈接&#xff1a;https://leetcode.cn/problems/implement-stack-using-queues/ 目錄 1. 題目描述 2. 思路分析 3. 代碼實現 1. 題目描述 2. 思路分析 可以用兩個隊列去實現一個棧&#xff0c;每次始終保持一個隊列為空。 入棧相當于給非空隊列進行入隊操作。 出棧相…

異步電機IM-改進的電壓模型磁鏈觀測器學習

導讀&#xff1a;本期文章主要介紹異步電機的改進型電壓模型磁鏈觀測器。傳統純積分形式的積分器在低速區域存在初始值問題和直流偏置問題&#xff0c;所以在實際應用中必須對電壓模型進行改進。本期文章中的對電壓模型改進是借鑒一篇IEEE中的方法。 如果需要文章中對應的仿真…

Apache Dubbo 云原生可觀測性的探索與實踐

作者&#xff1a;宋小生 - 平安壹錢包中間件資深工程師 Dubbo3 可觀測能力速覽 Apache Dubbo3 在云原生可觀測性方面完成重磅升級&#xff0c;使用 Dubbo3 最新版本&#xff0c;你只需要引入 dubbo-spring-boot-observability-starter 依賴&#xff0c;微服務集群即原生具備以…

貪心算法實現找零問題

思路&#xff1a; 使用 貪心算法 的思想 題目&#xff1a; 檸檬水找零 在檸檬水攤上&#xff0c;每一杯檸檬水的售價為5美元。顧客排隊購買你的產品,一次購買一杯。 每位顧客只買一杯檸檬水,然后向你付5美元、10美元或20美元。必須給每個顧客正確找零 注意,一開始你手頭沒有任何…

PSP - 基于擴散生成模型預測蛋白質結構 EigenFold 算法與環境配置

歡迎關注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/132357976 Paper: EigenFold: Generative Protein Structure Prediction with Diffusion Models EigenFold 是用于蛋白質結構預測的擴散生成模型…

使用深度學習實現的圖像偽造檢測: 一個Python畢業項目指南

1. 引言 在當前的數字化時代&#xff0c;圖像處理和偽造技術越來越先進。從影視制作到社交媒體&#xff0c;人們常常與修飾或改變過的圖片打交道。雖然這為創意產業提供了無數機會&#xff0c;但也為不誠實的內容創造者帶來了偽造和篡改圖像的機會。因此&#xff0c;圖像偽造檢…

Selenium手動和自動兩種方式啟動Chrome驅動

1. 自動啟動chrome驅動(已經安裝了Selenium庫和Chrome驅動) 要使用Selenium自動跟隨自帶的Chrome驅動&#xff0c;你需要首先確保你已經安裝了Selenium庫和Chrome驅動。然后&#xff0c;你可以按照以下步驟進行操作&#xff1a; 導入必要的庫&#xff1a; from selenium imp…

【面試八股文】每日一題:談談你對線程的理解

每日一題-Java核心-談談你對線程的理解【面試八股文】 Java線程是Java程序中的執行單元。一個Java程序可以同時運行多個線程&#xff0c;每個線程可以獨立執行不同的任務。線程的執行是并發的&#xff0c;即多個線程可以同時執行。 1. 線程的特點 Java中的線程有如下的特點 輕…

react-native-webview使用postMessage后H5不能監聽問題(iOS和安卓的兼容問題)

/* 監聽rn消息 */ const eventListener nativeEvent > {//解析數據actionType、extraconst {actionType, extra} nativeEvent.data && JSON.parse(nativeEvent.data) || {} } //安卓用document&#xff0c;ios用window window.addEventListener(message, eventLis…