如果您最近从使用react到next.js过渡,则必须遇到此错误“ 错误:水合失败,因为初始UI与服务器上呈现的内容不匹配 ”。让我们了解为什么通常会发生此错误以及如何解决该错误。
什么是水合?
在Next.js中,页面的第一个渲染是在服务器上进行的。然后将此预渲染的HTML提供给客户。在客户端,React接管此HTML页面以使此页面交互式(基本上它将事件处理程序连接到DOM节点)。这是水合。
为什么发生此错误?
在此过程中,React还具有预渲染的HTML外观的模型(以便它可以将事件处理程序连接到必要的JS交互性),如果初始渲染的客户端版本与pre-pre-pre-pre-pre-从服务器渲染HTML,我们得到此错误。
某些情况可能会出现此错误:
-
您使用浏览器API来有条件地渲染组件/页面:在这种情况下,由于浏览器API(LocalStorage,SessionStorage)在服务器上不可用,因此预渲染的HTML可以不同客户端。
// I will use this atom in the solutions section :) const defaultState={ username:"", id:"", isLoggedIn:false } export const adminState=atom<IAdmin>({ key:"currentAdmin", default: (typeof window !== 'undefined') ? ( localStorage.getItem('user') ? JSON.parse(localStorage.getItem('user') as string) : defaultState ) : defaultState }) //if this state is used to conditionally render, it will cause hydration error
在组件中使用此后坐状状态时,将出现水合错误,因为在服务器上,HTML将根据默认状态呈现HTML,并且在客户端端上,由于localStorage,HTML会有所不同。
。 -
您的HTML语法不是正确的:在这种情况下,您可能以某种怪异的方式使用了JSX。一些例子:
<p><div>logout</div></p> <p><p>Your text</p></p>
-
一些浏览器扩展改变客户端的HTML。
解决此错误的解决方案:
-
使用效果的重新配置逻辑:
服务器在呈现服务器端的HTML时忽略了使用效应块。使用效果仅在客户端运行,并且可以访问所有浏览器API。
// I am using the above mentioned state atom const RequireAuth: React.FC<{ children: ReactElement }> = ({ children }) => { const [loader, setLoader] = useState(true); const user = useRecoilValue(userState); const router = useRouter(); useEffect(() => { if (user.isLoggedIn) { setLoader(false); } else router.replace('/login'); }, []); return <>{!loader && children}</>; }; // As user.isLoggedIn depends on localStorage, // we check for it in the useEffect (client side)
-
在某些组件上禁用SSR,在客户端可能有所不同:
import dynamic from 'next/dynamic'; //code for YourComponent export default dynamic(() => Promise.resolve(YourComponent), { ssr: false });
-
对于时间戳,预渲染的HTML将与客户端版本不同。在这种情况下,您可以通过在元素中使用抑制水力= {true}来抑制警告。
其他建议:而不是在客户端渲染整个页面,而是考虑将需要客户端渲染的零件抽象成单独的组件。利用上述方法渲染它们,从您的末端进行了一些调整。
关于安全性的注释:在上面的文章中,我将JWT令牌存储在LocalStorage中,这不是一个好的做法。更好的解决方案可能包括使用cookie进行身份验证。如果您使用的是cookie,则可以尝试使用getServersideProps()在服务器端获得身份验证状态本身。
在Twitter上与我联系| Linkedin | Github
愉快的编码! ðð