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

NextJS中localStorage.getItem()在组件中无法正常工作的问题

解决NextJS中Nav组件获取localStorage旧值的问题

问题根源

Nav组件里的useEffect依赖项是空数组,只会在组件首次挂载时执行一次。后续页面切换导致localStorage更新时,这个useEffect不会重新触发,所以始终读取的是初始挂载时的旧值。

可行解决方案

方案1:监听浏览器storage事件

利用浏览器原生的storage事件,当localStorage中的page键发生变化时,自动更新Nav组件的状态。

修改Nav.tsx代码:

const Nav = () => {
  const [pageData, setPageData] = useState();

  useEffect(() => {
    // 初始化读取一次存储数据
    const initData = JSON.parse(localStorage.getItem('page'));
    if (initData) {
      setPageData(initData);
    }

    // 监听storage变化
    const handleStorageUpdate = (e: StorageEvent) => {
      if (e.key === 'page' && e.newValue) {
        setPageData(JSON.parse(e.newValue));
      }
    };

    window.addEventListener('storage', handleStorageUpdate);
    // 组件卸载时移除监听
    return () => window.removeEventListener('storage', handleStorageUpdate);
  }, []);

  return (...some html);
};

注意:这个事件仅在不同标签页/窗口修改localStorage时触发,同页面内修改不会触发,适合多窗口同步场景。

方案2:监听NextJS路由切换事件

因为你的场景是路由切换导致页面数据更新,直接监听NextJS的路由完成事件,每次路由切换后重新读取localStorage。

修改Nav.tsx代码:

import { useRouter } from 'next/router';

const Nav = () => {
  const [pageData, setPageData] = useState();
  const router = useRouter();

  useEffect(() => {
    // 封装读取数据的函数
    const loadPageData = () => {
      const current = JSON.parse(localStorage.getItem('page'));
      if (current) {
        setPageData(current);
      }
    };

    // 初始化读取
    loadPageData();

    // 路由切换完成后重新读取
    const handleRouteChange = () => loadPageData();
    router.events.on('routeChangeComplete', handleRouteChange);

    // 组件卸载时移除监听
    return () => router.events.off('routeChangeComplete', handleRouteChange);
  }, [router]);

  return (...some html);
};

方案3:改用React Context(推荐)

跨组件共享状态时,React Context比localStorage更适配NextJS的应用状态管理,能彻底避免本地存储的同步问题。

  1. 创建PageContext.tsx:
import { createContext, useContext, useState, ReactNode } from 'react';

type PageData = {
  title: string;
  subtitle: string;
  slug: string;
};

type PageContextType = {
  pageData: PageData | null;
  setPageData: (data: PageData) => void;
};

const PageContext = createContext<PageContextType | undefined>(undefined);

export const PageProvider = ({ children }: { children: ReactNode }) => {
  const [pageData, setPageData] = useState<PageData | null>(null);
  return (
    <PageContext.Provider value={{ pageData, setPageData }}>
      {children}
    </PageContext.Provider>
  );
};

export const usePageContext = () => {
  const context = useContext(PageContext);
  if (!context) {
    throw new Error('usePageContext必须在PageProvider内部使用');
  }
  return context;
};
  1. 在_app.tsx中挂载Provider:
import { PageProvider } from '../path-to/PageContext';

export default function App({ Component, pageProps }) {
  return (
    <PageProvider>
      <Component {...pageProps} />
    </PageProvider>
  );
}
  1. 修改[slug].tsx更新Context状态:
import { usePageContext } from '../path-to/PageContext';

export default function Page({ data }) {
  const { setPageData } = usePageContext();

  useEffect(() => {
    const page = {
      title: data.page.title,
      subtitle: data.page.subtitle,
      slug: data.page.slug,
    };
    setPageData(page);
    // 可选:同时存入localStorage做持久化
    localStorage.setItem("page", JSON.stringify(page));
  }, [data, setPageData]);

  return (...some html);
}
  1. 修改Nav.tsx直接读取Context数据:
import { usePageContext } from '../path-to/PageContext';

const Nav = () => {
  const { pageData } = usePageContext();

  // 直接使用pageData即可,无需手动读取localStorage
  return (...some html);
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 06:20:30