You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Next.js中使用localStorage隐藏Div时刷新闪烁问题

解决Next.js中页面刷新时Div短暂闪烁的问题

问题原因

你当前代码里,showBanner初始值设为true,组件首次渲染时会先显示Banner区域;而读取localStorage的逻辑放在useEffect中,这个钩子要等组件挂载后才执行,此时才会根据本地存储的值更新状态,所以会出现刷新时Banner短暂显示再消失的闪烁现象。

解决方案

方法一:初始化状态时直接读取localStorage

在useState的初始化函数里直接读取本地存储的值,避免先渲染初始状态再更新。同时兼容服务器端渲染(Next.js服务端没有window对象):

const [showBanner, setShowBanner] = useState(() => {
  // 仅在客户端环境读取localStorage
  if (typeof window !== 'undefined') {
    const savedState = window.localStorage.getItem('STATE');
    return savedState ? JSON.parse(savedState) : true;
  }
  // 服务端默认返回true,客户端渲染时会覆盖
  return true;
});

useEffect(() => {
  window.localStorage.setItem('STATE', JSON.stringify(showBanner));
}, [showBanner]);

这样组件首次渲染时就会用localStorage中保存的状态,不会出现闪烁。

方法二:使用useLayoutEffect(效果有限)

把读取localStorage的逻辑放在useLayoutEffect中,它会在DOM更新前同步执行,比普通useEffect更早触发,能缩短闪烁时长,但不如方法一彻底:

const [showBanner, setShowBanner] = useState(true);

useLayoutEffect(() => {
  const data = window.localStorage.getItem('STATE');
  if (data !== null) setShowBanner(JSON.parse(data));
}, []);

useEffect(() => {
  window.localStorage.setItem('STATE', JSON.stringify(showBanner));
}, [showBanner]);

方法三:动态导入组件并禁用SSR

如果Banner组件不需要服务器端渲染,可以用Next.js的next/dynamic动态导入,确保组件仅在客户端渲染,初始化时就能读取localStorage:

先创建单独的Banner组件(比如Banner.js):

import { useState, useEffect } from 'react';

export default function Banner() {
  const [showBanner, setShowBanner] = useState(() => {
    const savedState = window.localStorage.getItem('STATE');
    return savedState ? JSON.parse(savedState) : true;
  });

  useEffect(() => {
    window.localStorage.setItem('STATE', JSON.stringify(showBanner));
  }, [showBanner]);

  if (!showBanner) return null;

  return (
    <div>
      <div>
        <h2>Welcome</h2>
        <p>Sign up for my newsletter</p>
      </div>
      <button onClick={() => setShowBanner(false)}>Hide</button>
    </div>
  );
}

再在页面中动态导入:

import dynamic from 'next/dynamic';

const Banner = dynamic(() => import('../components/Banner'), { ssr: false });

export default function Home() {
  return (
    <div>
      <Banner />
    </div>
  );
}

推荐方案

优先选方法一,它最简单且能从根源解决闪烁问题,同时兼容服务器端渲染场景。

内容的提问来源于stack exchange,提问作者Rain Man

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 09:50:41