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

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

開發(fā) 前端
直到最近,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是穩(wěn)定的,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不匹配!

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

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

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

  1. function Checkbox() { 
  2.   // 生成唯一、穩(wěn)定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來了,一切都變了

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

  1. // 全局通用的計數(shù)變量 
  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,可以根據(jù)用戶交互改變hydrate的順序。

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

此時React會優(yōu)先對右下角部分hydrate:

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

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

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

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

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的實際實現(xiàn)中,層級被表示為「32進制」的數(shù)。

之所以選擇「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數(shù)據(jù)的棧)。

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

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

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

參考資料

[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并發(fā)的React組件render

2024-07-16 09:51:39

HTMLHookReact

2022-03-30 14:22:55

ReactReact18并發(fā)特性

2023-03-21 08:31:13

ReconcilerFiber架構

2022-02-28 10:30:03

架構代碼Native

2022-04-27 07:37:42

ReactReact18

2022-05-16 08:00:55

ReactReact 18數(shù)組

2022-10-14 08:45:54

2024-04-24 11:00:05

React 18Fiber

2023-03-28 07:59:57

ReactReconciler

2024-04-01 13:08:24

唯一IDC#后端

2022-02-23 07:09:30

分布式ID雪花算法

2022-03-25 08:31:09

ReactReact 18升級

2022-04-18 08:57:32

React 18前端

2022-07-06 15:07:47

React開發(fā)

2021-08-22 17:27:50

KDE PlasmaWindows概覽效果
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 91在线第一页 | 欧美一区二区三区在线观看 | 正在播放国产精品 | 精品av | 亚洲视频在线看 | 婷婷色国产偷v国产偷v小说 | 一区二区三| 国产精品久久亚洲 | 亚洲男人天堂 | 国产精品成人一区二区三区 | 精品国产乱码久久久久久老虎 | 超碰免费在线观看 | 亚洲人成在线播放 | 91观看| 欧美极品在线观看 | 黄色电影在线免费观看 | 日本三级精品 | 亚洲一区二区三区在线视频 | 免费看91 | 99re国产精品 | 91精品国产综合久久久久久蜜臀 | 日韩成人| 日韩中文在线 | 日韩一级免费观看 | 天堂av中文在线 | 观看av| 四虎伊人 | 午夜精品一区二区三区三上悠亚 | 久久亚洲精品国产精品紫薇 | 日日干夜夜操天天操 | 在线观看黄色电影 | 亚洲欧美日韩精品 | 亚洲激情综合 | 国产97人人超碰caoprom | 这里精品 | 久久久亚洲精品视频 | 亚洲国产激情 | 一本色道久久综合亚洲精品高清 | 成人av电影网 | 中文字幕亚洲一区二区va在线 | 国产在线精品一区二区 |