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

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

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

[[400053]]

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

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

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

問題一:DOM/BOM 缺失

SSR 是在 node 環(huán)境下運(yùn)行 React 代碼,而此時(shí) window、document、navigator 等全局屬性沒有。如果直接使用了這些屬性,就會(huì)報(bào)錯(cuò) window is not defined, document is not defined, navigator is not defined 等。

常見的錯(cuò)誤用法是在 Hooks 執(zhí)行過程中,直接使用了 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 中(服務(wù)端不會(huì)執(zhí)行),避免服務(wù)端執(zhí)行時(shí)報(bào)錯(cuò),例如:

  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] 來做環(huán)境判斷

  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 模式下,會(huì)出現(xiàn)以下警告

  • ⚠️ 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. 根據(jù)環(huán)境動(dòng)態(tài)的指定是使用 useEffect 還是 useLayoutEffect。這是來自社區(qū)的一種 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; 

總結(jié):寫 Hooks 時(shí)需要注意

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

2.在非 useEffect/useLayoutEffect 使用 DOM/BOM 屬性時(shí),使用 isBrowser 判斷是否在瀏覽器環(huán)境執(zhí)行

3.如果某個(gè) Hooks 需要接收 DOM/BOM 屬性,需要支持函數(shù)形式傳參。以 ahooks 的 useEventListener 舉例,必須支持函數(shù)形式來指定 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 服務(wù)端渲染[7]
  • useLayoutEffect and SSR[8]

參考資料

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

https://umijs.org/zh-CN/docs/SSR#服務(wù)端渲染(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 服務(wù)端渲染:

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

本文轉(zhuǎn)載自微信公眾號(hào)「前端技術(shù)磚家」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系前端技術(shù)磚家公眾號(hào)。

 

責(zé)任編輯:姜華 來源: 前端技術(shù)磚家
相關(guān)推薦

2019-10-08 16:05:19

Redis數(shù)據(jù)庫系統(tǒng)

2019-04-04 13:11:37

React內(nèi)存泄露memory leak

2010-08-31 16:09:04

DIV+CSS

2010-09-01 14:51:12

CSSIEFirefox

2024-07-08 08:45:41

2011-07-26 16:05:19

Oracle數(shù)據(jù)庫服務(wù)器

2016-09-27 21:14:53

JavaURL

2014-01-07 13:54:02

HadoopYARN

2024-05-24 10:56:24

PythonURL代碼

2024-10-30 11:00:00

Python列表索引

2021-08-05 08:32:27

React開發(fā)項(xiàng)目

2010-08-26 12:59:29

marginCSS

2010-08-04 10:20:30

Flex組件開發(fā)

2023-04-12 11:32:33

網(wǎng)絡(luò)

2025-01-09 15:28:30

2025-02-19 08:00:00

移動(dòng)端移動(dòng)設(shè)備移動(dòng)開發(fā)

2021-08-20 15:49:13

電腦主板維修

2024-05-09 15:00:38

Python編碼開發(fā)

2011-05-06 17:25:58

硒鼓

2009-12-24 11:13:41

點(diǎn)贊
收藏

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