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

為了生成唯一id,React18專門引入了新Hook:useId

開發 前端
直到最近,React18推出了官方Hook——useId,雖然用法簡單,但背后的原理卻很有意思 —— 每個id代表該組件在組件樹中的層級結構。

[[437140]]

大家好,我卡頌。

看看如下組件有什么問題:

  1. // App.tsx 
  2. const id = Math.random(); 
  3.  
  4. export default function App() { 
  5.   return <div id={id}>Hello</div> 

如果應用是CSR(客戶端渲染),id是穩定的,App組件沒有問題。

但如果應用是SSR(服務端渲染),那么App.tsx會經歷:

  1. React在服務端渲染,生成隨機id(假設為0.1234),這一步叫dehydrate(脫水)
  2. <div id="0.12345">Hello</div>作為HTML傳遞給客戶端,作為首屏內容
  3. React在客戶端渲染,生成隨機id(假設為0.6789),這一步叫hydrate(注水)

客戶端、服務端生成的id不匹配!

事實上,服務端、客戶端無法簡單生成穩定、唯一的id是個由來已久的問題,早在15年就有人提過issue:

Generating random/unique attributes server-side that don't break client-side mounting[1]

直到最近,React18推出了官方Hook——useId,才解決以上問題。他的用法很簡單:

  1. function Checkbox() { 
  2.   // 生成唯一、穩定id 
  3.   const id = useId(); 
  4.   return ( 
  5.     <> 
  6.       <label htmlFor={id}>Do you like React?</label> 
  7.       <input type="checkbox" name="react" id={id} /> 
  8.     </> 
  9.   ); 
  10. ); 

雖然用法簡單,但背后的原理卻很有意思 —— 每個id代表該組件在組件樹中的層級結構。

本文讓我們來了解useId的原理。

React18來了,一切都變了

這個問題雖然一直存在,但之前一直可以使用自增的全局計數變量作為id,考慮如下例子:

  1. // 全局通用的計數變量 
  2. let globalIdIndex = 0; 
  3.  
  4.  
  5. export default function App() { 
  6.   const id = useState(() => globalIdIndex++); 
  7.   return <div id={id}>Hello</div> 

只要React在服務端、客戶端的運行流程一致,那么雙端產生的id就是對應的。

但是,隨著React Fizz(React新的服務端流式渲染器)的到來,渲染順序不再一定。

比如,有個特性叫 Selective Hydration,可以根據用戶交互改變hydrate的順序。

當下圖左側部分在hydrate時,用戶點擊了右下角部分:

此時React會優先對右下角部分hydrate:

關于Selective Hydration更詳細的解釋見:New Suspense SSR Architecture in React 18[2]

如果應用中使用自增的全局計數變量作為id,那么顯然先hydrate的組件id會更小,所以id是不穩定的。

那么,有沒有什么是服務端、客戶端都穩定的標記呢?

答案是:組件的層次結構。

useId的原理

假設應用的組件樹如下圖:

不管B和C誰先hydrate,他們的層級結構是不變的,所以「層級」本身就能作為服務端、客戶端之間不變的標識。

比如B可以使用2-1作為id,C使用2-2作為id:

  1. function B() { 
  2.   // id為"2-1" 
  3.   const id = useId(); 
  4.   return <div id={id}>B</div>; 

實際需要考慮兩個要素:

1. 同一個組件使用多個id

比如這樣:

  1. function B() { 
  2.   const id0 = useId(); 
  3.   const id1 = useId(); 
  4.   return ( 
  5.     <ul> 
  6.       <li id={id0}></li> 
  7.       <li id={id1}></li> 
  8.     </ul> 
  9.   ); 

2. 要跳過沒有使用useId的組件

還是考慮這個組件樹結構:

如果組件A、D使用了useId,B、C沒有使用,那么只需要為A、D劃定層級,這樣就能「減少需要表示層級」。

在useId的實際實現中,層級被表示為「32進制」的數。

之所以選擇「32進制」,是因為選擇盡可能大的進制會讓生成的字符串盡可能緊湊。比如:

  1. const a = 18; 
  2.  
  3. // "10010" length 5 
  4. a.toString(2)    
  5.  
  6. //  "i" length 1 
  7. a.toString(32)   

具體的useId層級算法參考useId[3]

總結

React源碼內部有多種棧結構(比如用于保存context數據的棧)。

useId 棧的邏輯是其中比較復雜的一種。

誰能想到用法如此簡單的API背后,實現起來居然這么復雜?

React團隊搗鼓「并發特性」,真挺不容易的...

參考資料

[1]Generating random/unique attributes server-side that don't break client-side mounting:

https://github.com/facebook/react/issues/4000

[2]New Suspense SSR Architecture in React 18:

https://github.com/reactwg/react-18/discussions/37

[3]useId:

https://github.com/facebook/react/pull/22644

 

責任編輯:姜華 來源: 魔術師卡頌
相關推薦

2021-11-01 19:49:55

React組件模式

2021-06-22 07:45:57

React18startTransiReact

2021-06-22 07:30:07

React18Automatic b自動批處理

2021-06-16 06:05:25

React18React

2022-03-16 17:01:35

React18并發的React組件render

2024-07-16 09:51:39

HTMLHookReact

2022-02-28 10:30:03

架構代碼Native

2023-03-21 08:31:13

ReconcilerFiber架構

2022-03-30 14:22:55

ReactReact18并發特性

2022-04-27 07:37:42

ReactReact18

2022-05-16 08:00:55

ReactReact 18數組

2022-10-14 08:45:54

2024-04-24 11:00:05

React 18Fiber

2022-03-25 08:31:09

ReactReact 18升級

2022-04-18 08:57:32

React 18前端

2022-07-06 15:07:47

React開發

2024-04-01 13:08:24

唯一IDC#后端

2022-02-23 07:09:30

分布式ID雪花算法

2023-03-28 07:59:57

ReactReconciler

2021-08-22 17:27:50

KDE PlasmaWindows概覽效果
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 视频一区 国产精品 | 成人乱人乱一区二区三区软件 | 丁香五月缴情综合网 | jizz亚洲人| 69av在线视频| 精品国产乱码久久久久久久久 | 免费欧美 | 亚洲一区二区三区四区五区午夜 | 亚洲精品视频在线看 | 国产精品一区三区 | 在线免费看毛片 | 成人综合一区 | 久久精品—区二区三区 | 91中文在线观看 | 高清黄色毛片 | 日日摸夜夜添夜夜添精品视频 | 成年人在线视频 | 精品视频在线一区 | 国产日韩一区二区三区 | 欧美日韩综合一区 | 国产丝袜一区二区三区免费视频 | 一区二区不卡视频 | 国产精品久久久久久久久久免费 | 在线一区视频 | 伊人精品国产 | 精品欧美一区二区三区久久久 | 午夜电影网站 | 一级黄色片一级黄色片 | 国产目拍亚洲精品99久久精品 | 亚洲瑟瑟 | 麻豆一区 | 69av在线视频 | 成人免费久久 | 国产成人一区二 | 特级做a爱片免费69 精品国产鲁一鲁一区二区张丽 | a毛片| 成人av网站在线观看 | 91在线第一页 | 在线成人av| 精品国产91亚洲一区二区三区www | www.玖玖玖 |