自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

避不開(kāi)的 setState 問(wèn)題

開(kāi)發(fā) 前端
在開(kāi)始講解異步特性之前,我們需要先明確,從 API 層面上說(shuō),它就是普通的調(diào)用執(zhí)行的函數(shù) ,自然是同步 API 。因此,這里所說(shuō)的同步和異步,指的是 API 調(diào)用后,state 的改變或者更新 DOM 的時(shí)機(jī),是同步還是異步的。

[[422711]]

本文轉(zhuǎn)載自微信公眾號(hào)「勾勾的前端世界」,作者西嶺 。轉(zhuǎn)載本文請(qǐng)聯(lián)系勾勾的前端世界公眾號(hào)。

異步的 setState

“setState 是異步還是同步的?”

這是一個(gè)面試中經(jīng)常會(huì)被問(wèn)到的經(jīng)典面試題。

在開(kāi)始講解異步特性之前,我們需要先明確,從 API 層面上說(shuō),它就是普通的調(diào)用執(zhí)行的函數(shù) ,自然是同步 API 。因此,這里所說(shuō)的同步和異步,指的是 API 調(diào)用后,state 的改變或者更新 DOM 的時(shí)機(jī),是同步還是異步的。

我們先來(lái)看一段代碼:

  1. import React, { Component } from'react' 
  2.  
  3. exportclass States extends Component { 
  4.   state = { 
  5.     name:"lisi"
  6.     age:18 
  7.   } 
  8.  
  9.   fun= ()=>{ 
  10.     this.setState({ 
  11.       name:'xiling' 
  12.     }) 
  13.     console.log(this.state.name
  14.   } 
  15.  
  16.   render() { 
  17.     return ( 
  18.       <div> 
  19.         <h2>State 組件</h2> 
  20.         <p>{this.state.name}</p> 
  21.         <buttononClick={()=>{this.fun()}}>點(diǎn)我</button> 
  22.       </div> 
  23.     ) 
  24.   } 
  25.  
  26. exportdefault States 

代碼實(shí)現(xiàn)的的功能非常簡(jiǎn)單,就是在點(diǎn)擊按鈕后,修改 state 中的 name 屬性值。事件處理函數(shù)中,是在調(diào)用 setState 方法之后,又將 state 的值打印到了控制臺(tái)。運(yùn)行代碼你會(huì)發(fā)現(xiàn), Dom 中的值發(fā)生了改變,但是控制臺(tái)卻是之前的結(jié)果值。

如果你對(duì)異步的運(yùn)行規(guī)則比較熟悉,你一定不會(huì)感到奇怪。很顯然,this.setState() 是異步執(zhí)行的,調(diào)用之后,后面的代碼就緊跟著執(zhí)行了,因此,控制臺(tái)打印的結(jié)果肯定是修改之前。

因此,我們可以確定,this.setState() 確實(shí)是異步調(diào)用執(zhí)行的代碼。

注意,此時(shí),你可以將 this.setState() 當(dāng)作普通的異步執(zhí)行代碼(再次強(qiáng)調(diào) JSX 就是 JS)。

那么,如果我想調(diào)整代碼獲取異步執(zhí)行結(jié)果,應(yīng)該怎么做呢?

既然可以看作為普通的異步代碼,想想也知道,其實(shí) this.setState() 方法還提供了第二個(gè)參數(shù),我們可以傳入一個(gè)回調(diào)函數(shù),這個(gè)函數(shù)就是異步結(jié)束后執(zhí)行的回調(diào)函數(shù),具體代碼修改如下:

  1. fun=async ()=>{ 
  2.     awaitthis.setState({ 
  3.       name:'xiling' 
  4.     },()=>{ 
  5.       console.log(this.state.name
  6.     }) 
  7.   } 

回調(diào)函數(shù)處理異步結(jié)果本來(lái)就是傳統(tǒng)的異步編碼方式,但是,我們也知道,異步中的回調(diào)函數(shù)有一個(gè)最大的問(wèn)題就是 “回調(diào)地獄”,那么既然是異步,我們是不是就可以封裝一個(gè) Promise 了呢?

當(dāng)然可以!

但是,封裝一個(gè) Promise 就顯得有些復(fù)雜。最簡(jiǎn)單的方式就是借助 ES 2017 中異步調(diào)用函數(shù) async/ await 來(lái)實(shí)現(xiàn)。我們直接修改事件處理函數(shù)即可,具體語(yǔ)法規(guī)則如下:

  1. fun=async ()=>{ 
  2.     awaitthis.setState({ 
  3.       name:'xiling' 
  4.     }) 
  5.     console.log(this.state.name
  6.   } 

setState 的執(zhí)行邏輯

在使用 this.setState() 進(jìn)行狀態(tài)更改時(shí),需要進(jìn)行邏輯處理應(yīng)該怎么做呢?

其實(shí) this.setState() 的第一個(gè)參數(shù)是可以接收一個(gè)函數(shù)處理的。需要注意的是,函數(shù)的運(yùn)行必須返回一個(gè) state 對(duì)象,具體代碼如下:

  1. fun = ()=>{ 
  2.     this.setState((state)=>{ 
  3.       // 函數(shù)邏輯代碼 …… 
  4.       let returnData 
  5.       returnData = state.age+1 
  6.       // 最終返回一個(gè)state 對(duì)象 
  7.       return { 
  8.         age:returnData 
  9.       } 
  10.     }) 
  11.   } 

也就是說(shuō) this.setState() 既可以接收對(duì)象參數(shù),也可以接收一個(gè)處理函數(shù)。

那么,這兩者又有什么區(qū)別呢?

在時(shí)間處理函數(shù)中,我們分別使用兩次 this.setState() 對(duì) state 進(jìn)行修改操作。

兩次函數(shù)執(zhí)行操作:

  1. fun = ()=>{ 
  2.     this.setState((state)=>{ 
  3.       return { 
  4.         age:state.age+2 
  5.       } 
  6.     }) 
  7.  
  8.     this.setState((state)=>{ 
  9.       return { 
  10.         age:state.age+3 
  11.       } 
  12.     }) 
  13.   } 

運(yùn)行代碼可以發(fā)現(xiàn),兩次 this.setState() 中的函數(shù)都得到了執(zhí)行,修改了 state 的值。我們?cè)賹⑼瑯拥拇a邏輯,使用對(duì)象數(shù)據(jù)的方式進(jìn)行修改操作:

  1. fun = ()=>{ 
  2.     this.setState({ 
  3.       age:this.state.age+2 
  4.     }) 
  5.     this.setState({ 
  6.       age:this.state.age+3 
  7.     }) 
  8.   } 

結(jié)果顯示,只有最后一次 this.setState() 得到了執(zhí)行。

沒(méi)錯(cuò),this.setState() 如果是函數(shù),那么函數(shù)會(huì)依次從上往下執(zhí)行;而如果是一個(gè)對(duì)象, React 會(huì)將多次 this.setState() 的調(diào)用合并為一次執(zhí)行,如果修改了相同的值,則會(huì)將前面的修改替換成最后一次的修改數(shù)據(jù)。

這一點(diǎn)在項(xiàng)目編碼中一定要牢記,避免出現(xiàn)意外的邏輯 Bug。

你可能會(huì)問(wèn),這到底是什么原理呢?我曾經(jīng)針對(duì)這個(gè)問(wèn)題做過(guò)一場(chǎng)專門(mén)的技術(shù)分享直播,直播的錄屏回放在這里,感興趣可以看看:https://www.bilibili.com/video/BV19P4y1W7hX。

(B站賬號(hào):西嶺老濕)

但是,對(duì)于新手來(lái)說(shuō),我建議你先收藏,因?yàn)槟悻F(xiàn)在真的可能看不懂。

當(dāng)然,你可能也發(fā)現(xiàn)了一個(gè)問(wèn)題,我們說(shuō)了那么多關(guān)于組件狀態(tài)的問(wèn)題,各種實(shí)驗(yàn)編碼都是在 class 類組件中完成的,那函數(shù)組件中是不是和類組件一樣呢?

嗯~ o( ̄▽ ̄)o……,因?yàn)?state 是類組件中的特性,而函數(shù)組件中的 state,需要具備 Hook 特性的知識(shí)作為鋪墊,所以,暫時(shí)我們先留個(gè)坑,等著后面來(lái)填就行了。

截至到目前,我們已經(jīng)掌握了組件的概念、組件的傳值、以及組件狀態(tài)的相關(guān)內(nèi)容。

 

責(zé)任編輯:武曉燕 來(lái)源: 勾勾的前端世界
相關(guān)推薦

2020-06-16 14:23:28

算法網(wǎng)絡(luò)Google

2015-09-18 11:28:23

2015-03-31 10:11:51

戴爾云計(jì)算DELL

2022-06-13 06:20:42

setStatereact18

2021-03-12 10:12:09

etState函數(shù)React

2017-04-12 11:15:52

ReactsetState策略

2021-06-29 09:47:34

ReactSetState機(jī)制

2020-02-23 18:00:18

數(shù)據(jù)泄露漏洞黑客

2022-08-08 17:38:45

Spring策略事務(wù)

2022-08-09 09:34:32

Spring開(kāi)發(fā)

2022-02-25 08:54:50

setState異步React

2017-01-16 17:17:23

存儲(chǔ)超融合架構(gòu)新聞

2019-01-24 10:18:25

機(jī)器學(xué)習(xí)深度學(xué)習(xí)圖像處理

2021-08-16 18:52:09

同步異步React

2009-05-11 14:48:11

2023-04-12 08:18:40

ChatGLM避坑微調(diào)模型

2016-03-30 09:54:59

bug報(bào)告開(kāi)發(fā)

2020-12-16 10:00:59

Serverless數(shù)字化云原生

2022-09-26 09:53:18

開(kāi)發(fā)緩存

2016-04-06 09:58:46

移動(dòng)·開(kāi)發(fā)技術(shù)周刊
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)