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

React Hooks 在 SSR 模式下常見問題及解決方案

開發 前端
由于 SSR 是在非瀏覽器環境執行 JS 代碼,所以會出現很多問題。本文主要介紹 React Hooks 在 SSR 模式下常見問題及解決方案。

[[400053]]

服務端渲染(Server-Side Rendering),是指由服務側完成頁面的 HTML 結構拼接的頁面處理技術。一般用于解決 SEO 問題和首屏加載速度問題。

由于 SSR 是在非瀏覽器環境執行 JS 代碼,所以會出現很多問題。本文主要介紹 React Hooks 在 SSR 模式下常見問題及解決方案。

更多關于 SSR 的介紹可以看 UmiJS 的文檔《服務端渲染(SSR)[1]》。

問題一:DOM/BOM 缺失

SSR 是在 node 環境下運行 React 代碼,而此時 window、document、navigator 等全局屬性沒有。如果直接使用了這些屬性,就會報錯 window is not defined, document is not defined, navigator is not defined 等。

常見的錯誤用法是在 Hooks 執行過程中,直接使用了 document 等全局屬性。

  1. import React, { useState } from 'react'
  2.  
  3. export default () => { 
  4.   const [state, setState] = useState(document.visibilityState); 
  5.   return state; 

解決方案

1.將訪問 DOM/BOM 的方法放在 useEffect/useLayoutEffect 中(服務端不會執行),避免服務端執行時報錯,例如:

  1. import React, { useState, useEffect } from 'react'
  2.  
  3. export default () => { 
  4.   const [state, setState] = useState(); 
  5.    
  6.   useEffect(()=>{ 
  7.     setState(document.visibilityState); 
  8.   }, []); 
  9.    
  10.   return state; 

2.通過 isBrowser[2] 來做環境判斷

  1. import React, { useState } from 'react'
  2.  
  3. function isBrowser() { 
  4.   return !!(typeof window !== 'undefined' && window.document && window.document.createElement); 
  5.  
  6. export default () => { 
  7.   const [state, setState] = useState(isBrowser() && document.visibilityState); 
  8.    
  9.   return state; 

問題二 useLayoutEffect Warning

如果使用了 useLayoutEffect,在 SSR 模式下,會出現以下警告

  • ⚠️ Warning: useLayoutEffect does nothing on the server, because its effect cannot be encoded into the server renderer's output format. This will lead to a mismatch between the initial, non-hydrated UI and the intended UI. To avoid this, useLayoutEffect should only be used in components that render exclusively on the client. See https://fb.me/react-uselayouteffect-SSR for common fixes.

解決方案

  1. 使用 useEffect 代替 useLayoutEffect(廢話)
  2. 根據環境動態的指定是使用 useEffect 還是 useLayoutEffect。這是來自社區的一種 hack 解決方案,目前在 react-redux[3]react-use[4]react-beautiful-dnd[5] 均使用的這種方案。
  1. import { useLayoutEffect, useEffect } from 'react'
  2. const useIsomorphicLayoutEffect = isBrowser() ? useLayoutEffect : useEffect; 
  3. export default useIsomorphicLayoutEffect; 

總結:寫 Hooks 時需要注意

1.不要在非 useEffect/useLayoutEffect 中,直接使用 DOM/BOM 屬性

2.在非 useEffect/useLayoutEffect 使用 DOM/BOM 屬性時,使用 isBrowser 判斷是否在瀏覽器環境執行

3.如果某個 Hooks 需要接收 DOM/BOM 屬性,需要支持函數形式傳參。以 ahooks 的 useEventListener 舉例,必須支持函數形式來指定 target 屬性。

  1. import React, { useState } from 'react'
  2. import { useEventListener } from 'ahooks'
  3.  
  4. export default () => { 
  5.   const [value, setValue] = useState(0); 
  6.  
  7.   const clickHandler = () => { 
  8.     setValue(value + 1); 
  9.   }; 
  10.  
  11.   useEventListener( 
  12.     'click',  
  13.     clickHandler,  
  14.     {  
  15. -       target: document.getElemenetById('click-btn')  
  16. +       target: () => document.getElemenetById('click-btn')  
  17.     } 
  18.   ); 
  19.  
  20.   return ( 
  21.     <button id="click-btn" type="button"
  22.       You click {value} times 
  23.     </button> 
  24.   ); 
  25. }; 

4.使用 useIsomorphicLayoutEffect 來代替 useLayoutEffect

參考資料

  • fix: useDocumentVisiblility support SSR[6]
  • UmiJS 服務端渲染[7]
  • useLayoutEffect and SSR[8]

參考資料

[1]服務端渲染(SSR):

https://umijs.org/zh-CN/docs/SSR#服務端渲染(SSR)

[2]isBrowser:

https://github.com/alibaba/hooks/blob/master/packages/hooks/src/utils/canUseDom.ts

[3]react-redux:

https://github.com/reduxjs/react-redux/blob/d16262582b2eeb62c05313fca3eb59dc0b395955/src/components/connectAdvanced.js#L40

[4]react-use:

https://github.com/streamich/react-use/blob/master/src/useIsomorphicLayoutEffect.ts

[5]react-beautiful-dnd:

https://github.com/atlassian/react-beautiful-dnd/blob/master/src/view/use-isomorphic-layout-effect.js

[6]fix: useDocumentVisiblility support SSR:

https://github.com/alibaba/hooks/pull/935/files

[7]UmiJS 服務端渲染:

https://umijs.org/zh-CN/docs/SSR#window-is-not-defined-document-is-not-defined-navigator-is-not-defined

[8]useLayoutEffect and SSR:

https://medium.com/@alexandereardon/uselayouteffect-and-SSR-192986cdcf7a

本文轉載自微信公眾號「前端技術磚家」,可以通過以下二維碼關注。轉載本文請聯系前端技術磚家公眾號。

 

責任編輯:姜華 來源: 前端技術磚家
相關推薦

2019-10-08 16:05:19

Redis數據庫系統

2019-04-04 13:11:37

React內存泄露memory leak

2010-08-31 16:09:04

DIV+CSS

2010-09-01 14:51:12

CSSIEFirefox

2024-07-08 08:45:41

2016-09-27 21:14:53

JavaURL

2011-07-26 16:05:19

Oracle數據庫服務器

2014-01-07 13:54:02

HadoopYARN

2024-10-30 11:00:00

Python列表索引

2024-05-24 10:56:24

PythonURL代碼

2023-04-12 11:32:33

網絡

2010-08-04 10:20:30

Flex組件開發

2010-08-26 12:59:29

marginCSS

2021-08-05 08:32:27

React開發項目

2025-01-09 15:28:30

2025-02-19 08:00:00

移動端移動設備移動開發

2024-05-09 15:00:38

Python編碼開發

2021-08-20 15:49:13

電腦主板維修

2009-12-24 11:13:41

2011-05-06 17:25:58

硒鼓
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 涩涩操| 亚洲播放 | 成人免费观看视频 | 国产成人99久久亚洲综合精品 | 91精品国产一区二区三区动漫 | 国产精品1 | 日韩视频一区二区三区 | 夜夜操天天艹 | 免费视频一区二区 | 性生生活大片免费看视频 | 国产不卡一区 | 国产伊人久久久 | 91不卡在线 | 国产精品揄拍一区二区 | 婷婷成人在线 | 91久久精品一区二区三区 | 欧美福利网站 | 大象一区 | 欧美精品福利视频 | 毛片入口 | 风间由美一区二区三区在线观看 | 日韩av最新网址 | 久久国产精品亚洲 | 欧美日韩在线一区二区三区 | 人干人操 | 国产一区二区三区网站 | 精产国产伦理一二三区 | 97久久久久久久久 | 国产一级在线 | 久久欧美精品 | 精品美女在线观看 | 久久9精品 | 国产一级黄色网 | 亚洲精品中文字幕在线观看 | 成人在线免费视频 | 亚洲成人999 | 午夜精品 | 精品久久国产 | 男人天堂久久 | 97超级碰碰 | 青青草一区二区三区 |