成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

使用 React/Hooks 時需要注意過時的閉包!

開發 前端
Hooks 簡化了 React 組件內部狀態和副作用的管理。此外,可以將重復的邏輯提取到自定義 Hooks 中,以在整個應用程序中重復使用。

[[383283]]

本文已經過原作者 Shadeed 授權翻譯。

Hooks 簡化了 React 組件內部狀態和副作用的管理。此外,可以將重復的邏輯提取到自定義 Hooks 中,以在整個應用程序中重復使用。

Hooks 嚴重依賴于 JS 閉包。這就是為什么 Hooks 如此具有表現力和簡單,但是閉包有時很棘手。

使用 Hooks 時可能遇到的一個問題就是過時的閉包,這可能很難解決。

讓我們從過時的裝飾開始。然后,看看到過時的閉包如何影響 React Hooks,以及如何解決該問題。

1.過時的閉包

工廠函數 createIncrement(incBy) 返回一個increment和log函數的元組。調用時,increment()函數將內部value增加incBy,而log()僅打印一條消息,其中包含有關當前value的信息:

  1. function createIncrement(incBy) { 
  2.   let value = 0; 
  3.  
  4.   function increment() { 
  5.     value += incBy; 
  6.     console.log(value); 
  7.   } 
  8.  
  9.  const message = `Current value is ${value}`; function log() { console.log(message); }   
  10.   return [increment, log]; 
  11.  
  12. const [increment, log] = createIncrement(1); 
  13. increment(); //  1 
  14. increment(); //  2 
  15. increment(); //  3 
  16. // 不能正確工作! 
  17. log();       //  "Current value is 0" 

[increment, log] = createIncrement(1)返回一個函數元組:一個函數增加內部值,另一個函數記錄當前值。

然后,increment()的3次調用將 value遞增到3。

最后,log()調用打印消息是 Current value is 0,這有點出乎意料的,因為此時 value 為 3 了。

log()是一個過時的閉包。閉包 log()捕獲了值為 "Current value is 0"的 message變量。

即使 value 變量在調用increment()時被增加多次,message變量也不會更新,并且總是保持一個過時的值 "Current value is 0"。

過時的閉包捕獲具有過時值的變量。

2.修復過時的閉包

修復過時的log()問題需要關閉實際更改的變量:value的閉包。

我們將語句 const message = ...; 移動到 log() 函數內部:

  1. function createIncrement(incBy) { 
  2.   let value = 0; 
  3.  
  4.   function increment() { 
  5.     value += incBy; 
  6.     console.log(value); 
  7.   } 
  8.  
  9.   function log() { 
  10.  const message = `Current value is ${value}`;    console.log(message); 
  11.   } 
  12.    
  13.   return [increment, log]; 
  14.  
  15. const [increment, log] = createIncrement(1); 
  16. increment(); //  1 
  17. increment(); //  2 
  18. increment(); //  3 
  19. // Works! 
  20. log();       // "Current value is 3" 

現在,在調用了 3 次 increment() 函數之后,調用 log() 記錄了實際value:"Current value is 3"。

3. Hooks 中的過時閉包

3.1 useEffect()

我們來看一下使用useEffect() 過時閉包的常見情況。

在組件中,useEffect() 中每2秒記錄一次count的值

  1. function WatchCount() { 
  2.   const [count, setCount] = useState(0); 
  3.  
  4.   useEffect(function() { 
  5.     setInterval(function log() { 
  6.       console.log(`Count is: ${count}`); 
  7.     }, 2000); 
  8.   }, []); 
  9.  
  10.   return ( 
  11.     <div> {count} <button onClick={() => setCount(count + 1) }> Increase </button> </div> 
  12.   ); 

打開事例(https://codesandbox.io/s/stale-closure-use-effect-broken-2-gyhzk)

并點擊幾次增加按鈕。然后看看控制臺,每2秒出現一次Count is: 0,盡管count狀態變量實際上已經增加了幾次。

為什么會這樣?

第一次渲染時,狀態變量count初始化為0。

組件安裝后,useEffect()調用 setInterval(log, 2000)計時器函數,該計時器函數計劃每2秒調用一次log()函數。在這里,閉包log()捕獲到count變量為0。

之后,即使在單擊Increase按鈕時count增加,計時器函數每2秒調用一次的log(),使用count的值仍然是0。log()成為一個過時的閉包。

解決方案是讓useEffect()知道閉包log()依賴于count,并在count改變時正確處理間隔的重置

  1. function WatchCount() { 
  2.   const [count, setCount] = useState(0); 
  3.  
  4.   useEffect(function() { 
  5.     const id = setInterval(function log() { 
  6.       console.log(`Count is: ${count}`); 
  7.     }, 2000); 
  8.     return function() { 
  9.       clearInterval(id); 
  10.     } 
  11.  }, [count]); 
  12.   return ( 
  13.     <div> 
  14.  {count
  15.  <button onClick={() => setCount(count + 1) }> 
  16.  Increase 
  17.  </button> 
  18.  </div> 
  19.   ); 

正確設置依賴項后,一旦count發生變化,useEffect()就會更新閉包。

3.2 useState()

組件有1個button ,以1秒延遲異步增加計數器。

  1. function DelayedCount() { 
  2.   const [count, setCount] = useState(0); 
  3.  
  4.   function handleClickAsync() { 
  5.     setTimeout(function delay() { 
  6.       setCount(count + 1); 
  7.     }, 1000); 
  8.   } 
  9.  
  10.   return ( 
  11.     <div> {count} <button onClick={handleClickAsync}>Increase async</button> </div> 
  12.   ); 

現在打開演示(https://codesandbox.io/s/use-state-broken-0q994)。快速單擊2次按鈕。計數器僅更新為1,而不是預期的2。

每次單擊setTimeout(delay, 1000)將在1秒后執行delay()。delay()此時捕獲到的 count 為 0。

兩個delay()都將狀態更新為相同的值:setCount(count + 1) = setCount(0 + 1) = setCount(1)。

這是因為第二次單擊的delay()閉包中已捕獲了過時的count變量為0。

為了解決這個問題,我們使用函數式方法setCount(count => count + 1)來更新count狀態

  1. function DelayedCount() { 
  2.   const [count, setCount] = useState(0); 
  3.  
  4.   function handleClickAsync() { 
  5.     setTimeout(function delay() { 
  6.  setCount(count => count + 1);    }, 1000); 
  7.   } 
  8.  
  9.   function handleClickSync() { 
  10.     setCount(count + 1); 
  11.   } 
  12.  
  13.   return ( 
  14.     <div> 
  15.  {count
  16.  <button onClick={handleClickAsync}>Increase async</button> 
  17.  <button onClick={handleClickSync}>Increase sync</button> 
  18.  </div> 
  19.   ); 

打開演示(https://codesandbox.io/s/use-state-fixed-zz78r)。再次快速單擊按鈕2次。計數器顯示正確的值2。

當一個返回基于前一個狀態的新狀態的回調函數被提供給狀態更新函數時,React確保將最新的狀態值作為該回調函數的參數提供

  1. setCount(alwaysActualStateValue => newStateValue); 

這就是為什么在狀態更新過程中出現的過時裝飾問題可以通過函數這種方式來解決。

4.總結

當閉包捕獲過時的變量時,就會發生過時的閉包問題。

解決過時閉包的有效方法是正確設置React鉤子的依賴項。或者,在失效狀態的情況下,使用函數方式更新狀態。

~完,我是小智,我要去刷碗了。

 

作者:Shadeed 譯者:前端小智 來源:dmitripavlutin原文:https://dmitripavlutin.com/react-hooks-stale-closures/

 本文轉載自微信公眾號「大遷世界」,可以通過以下二維碼關注。轉載本文請聯系大遷世界公眾號。

 

責任編輯:武曉燕 來源: 大遷世界
相關推薦

2022-05-04 10:38:58

React閉包組件

2024-01-08 08:35:28

閉包陷阱ReactHooks

2022-05-05 08:31:48

useRefuseEffecthook

2024-05-16 15:15:14

2012-07-04 14:40:37

Ajax

2023-12-13 15:20:45

數據中心云計算人工智能

2021-03-09 09:52:55

技術React Hooks'數據

2016-11-24 15:54:06

androidJSONObject

2019-06-23 16:02:12

Kubernetes集群節點高并發

2023-01-05 07:49:03

2023-07-27 18:39:20

低代碼開發編碼

2011-08-08 15:06:36

布線綜合布線智能家居

2011-12-21 09:54:15

項目經理

2010-06-29 15:54:36

UML建模

2010-09-29 12:59:53

MotorolaJ2ME

2010-05-26 17:05:13

SVN提交

2023-08-25 10:49:37

數據中心服務器

2011-05-26 17:37:11

Ajax

2025-03-28 00:45:00

JavaScript閉包React

2023-12-28 09:54:22

Java內存開發
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲精品91 | 亚洲成人999 | 亚洲一区 中文字幕 | 免费黄色av | 亚洲精品一区二区另类图片 | 国产美女在线免费观看 | 亚洲视频在线一区 | 成人一级视频在线观看 | 69堂永久69tangcom | 成人性生交大片免费看中文带字幕 | 欧美一级特黄aaa大片在线观看 | 在线高清免费观看视频 | 欧美精品中文字幕久久二区 | 91精品久久久久久久久中文字幕 | 黄色成人国产 | 四虎影音 | 国产乱肥老妇国产一区二 | 免费日韩av网站 | 国产91亚洲精品一区二区三区 | 国产做a爱片久久毛片 | 日本亚洲欧美 | 久久人人爽人人爽人人片av免费 | 91麻豆精品国产91久久久资源速度 | 亚洲欧美另类在线 | 国产精品s色 | 免费超碰 | 成人在线视频观看 | 久久久av中文字幕 | 久久精品日 | 久久久久国产一区二区三区四区 | 欧美不卡一区二区三区 | 麻豆久久久9性大片 | 欧美成人一区二区 | 国产9999精品 | 久久国产精品视频 | 久久成人激情 | 亚洲网站观看 | 亚洲免费在线观看视频 | 亚洲精品国产一区 | 亚洲 欧美 日韩在线 | 免费视频一区二区三区在线观看 |