next.js出现Hydration failed

1,890 阅读1分钟

1、现象:

初步分别使用css媒体查询react-responsiveuseMediaQuery,进行移动端和pc端切换对比。使用useMediaQuery可以快速通过js获取当前的媒体查询,从而确定当前的屏幕是宽屏还是移动端屏幕。但是在pc端页面刷新会显出Hydration failed because the initial UI does not match what was rendered on the serve错误提醒信息。 错误.gif

2、原因:

主要是在服务器端渲染的HTML与客户端渲染的HTML不匹配

3、解决:

可以使用useMediaQuery+Dynamic Import+React-lazy,动态导入能延迟加载组件和模块,使得服务器端渲染(SSR)时只渲染必要的组件和模块,从而减少服务端和客户端ui不一致的可能性。整体效果如同所示(分别在移动端和pc端刷新页面,都会出现loading效果,然后从移动端切换到pc端或者pc端切换到移动端就没有loading字段了): 完整.gif

import dynamic from 'next/dynamic'

const MyComponentWithMediaQuery = dynamic(() => import('./MyComponentWithMediaQuery'), 
{
  ssr: false ,loading: () => <p>Loading...</p>
})

function MyPage() {
  return <MyComponentWithMediaQuery />
}
import { useDesktopQuery } from "@/util/useHooks";

const MyComponentWithMediaQuery = () => {
  const flag = useDesktopQuery();
  return <>{flag && "pc页面"}</>;
};

export default MyComponentWithMediaQuery;


4、结果:

  • 1、可以使用css的媒体查询@media处理成响应式,这样的好处可以快速在移动端和pc端切换。注意:如果pc端和移动端页面结构相差太多,会导致页面文件大小变大
  • 2、具体页面首屏方案可以在结构变化不大情况下,优先选择css媒体查询处理。其他页面情况可以使用动态导入,这样可以保证首屏体验效果