当前位置: 首页 > 科技观察

SSR模式ReactHooks常见问题及解决方法

时间:2023-03-12 08:00:18 科技观察

服务端渲染(Server-SideRendering)是指由服务端完成页面HTML结构拼接的页面处理技术。一般用于解决SEO问题和首屏加载速度问题。由于SSR是在非浏览器环境下执行JS代码,所以会出现很多问题。本文主要介绍SSR模式下ReactHooks的常见问题及解决方法。关于SSR的更多介绍,请参考UmiJS文档《服务端渲染(SSR)[1]》。问题1:缺少DOM/BOM。SSR是在node环境下运行React代码,但是此时window、document、navigator等全局属性是不可用的。如果直接使用这些属性,会报windowisnotdefined、documentisnotdefined、navigatorisnotdefined等错误。一个常见的错误是在执行Hooks时直接使用全局属性,例如document。importReact,{useState}from'react';exportdefault()=>{const[state,setState]=useState(document.visibilityState);returnstate;}解决方法1.将访问DOM/BOM的方法放在useEffect/useLayoutEffect(server不会执行),避免server执行时报错,例如:importReact,{useState,useEffect}from'react';exportdefault()=>{const[state,setState]=useState();useEffect(()=>{setState(document.visibilityState);},[]);returnstate;}2。使用isBrowser[2]判断环境const[state,setState]=useState(isBrowser()&&document.visibilityState);returnstate;}问题2useLayoutEffect警告如果使用useLayoutEffect,在SSR模式下,会出现如下警告??警告:useLayoutEffect在服务端什么都不做,因为它效果无法编码为服务器渲染器的输出格式。这将导致初始的、未水化的UI和内部不匹配找到用户界面。为避免这种情况,useLayoutEffect只应在仅在客户端呈现的组件中使用。有关常见修复,请参阅https://fb.me/react-uselayouteffect-SSR。方案使用useEffect代替useLayoutEffect(废话)根据环境动态指定是使用useEffect还是useLayoutEffect。这是社区的hack方案,目前在react-redux[3]、react-use[4]、react-beautiful-dnd[5]中使用。import{useLayoutEffect,useEffect}from'react';constuseIsomorphicLayoutEffect=isBrowser()?useLayoutEffect:useEffect;exportdefaultuseIsomorphicLayoutEffect;总结:写Hooks时注意1.不要在非useEffect/useLayoutEffect中直接使用DOM/BOM属性2.useEffect/useLayoutEffect使用DOM/BOM属性时,使用isBrowser判断是否在浏览器环境下执行。3、如果某个Hooks需要接收DOM/BOM属性,需要支持函数形式传参。以ahooks的useEventListener为例,必须支持function形式指定target属性。importReact,{useState}from'react';import{useEventListener}from'ahooks';exportdefault()=>{const[value,setValue]=useState(0);constclickHandler=()=>{setValue(value+1);};useEventListener('click',clickHandler,{-target:document.getElemenetById('click-btn')+target:()=>document.getElemenetById('click-btn')});return(Youclick{value}times);};4.使用useIsomorphicLayoutEffect代替useLayoutEffectReference修复:useDocumentVisiblility支持SSR[6]UmiJS服务端渲染[7]useLayoutEffect和SSR[8]参考资料[1]服务端渲染(SSR):https://umijs.org/zh-CN/docs/SSR#ServerRendering(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]反应使用:https://github.com/streamich/react-use/blob/master/src/useIsomorphicLayoutEffect.ts[5]重新act-beautiful-dnd:https://github.com/atlassian/react-beautiful-dnd/blob/master/src/view/use-isomorphic-layout-effect.js[6]修复:useDocumentVisiblility支持SSR:https://github.com/alibaba/hooks/pull/935/files[7]UmiJS服务端渲染:https://umijs.org/zh-CN/docs/SSR#window-is-not-defined-document-是-not-defined-navigator-is-not-defined[8]useLayoutEffect和SSR:https://medium.com/@alexandereardon/uselayouteffect-and-SSR-192986cdcf7a,可以通过以下二维码关注并转载本文代码请联系前端技术砖公众号。