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

Next.js中Cookie存储对象数组失败?页面刷新状态丢失解决方案

解决方案

方案一:通过URL参数传递ID(推荐)

这是最可靠的方式,完全规避前端存储的问题,刷新页面、分享链接都能正常展示详情:

  • 卡片点击跳转时,把选中内容的唯一标识(比如YouTube视频ID)作为URL参数传递:
    import { useRouter } from 'next/router';
    
    // 卡片组件内的跳转逻辑
    const router = useRouter();
    const handleCardClick = (videoId) => {
      router.push(`/video/${videoId}`);
    };
    
  • 新建动态路由页面pages/video/[id].js,通过getStaticProps(或getServerSideProps)根据ID拉取详情:
    export async function getStaticProps({ params }) {
      const { id } = params;
      // 调用YouTube API获取对应视频详情
      const res = await fetch(`https://www.googleapis.com/youtube/v3/videos?id=${id}&key=你的API密钥&part=snippet`);
      const data = await res.json();
      const videoDetails = data.items[0];
    
      return {
        props: { videoDetails },
        // 可选:设置页面自动重新生成的间隔(秒)
        revalidate: 60,
      };
    }
    
    // 配置静态路径生成规则,支持未预定义的路径
    export async function getStaticPaths() {
      // 从播放列表API中获取所有视频ID(根据实际返回结构调整)
      const res = await fetch(`https://www.googleapis.com/youtube/v3/playlists?id=你的播放列表ID&key=你的API密钥&part=contentDetails`);
      const data = await res.json();
      const videoIds = data.items[0]?.contentDetails?.items?.map(item => item.resourceId.videoId) || [];
    
      return {
        paths: videoIds.map(id => ({ params: { id } })),
        fallback: true, // 允许访问未预生成的路径,Next.js会实时生成页面
      };
    }
    
    export default function VideoDetail({ videoDetails }) {
      if (!videoDetails) return <div>加载中...</div>;
      return (
        <div>
          <h1>{videoDetails.snippet.title}</h1>
          <p>{videoDetails.snippet.description}</p>
        </div>
      );
    }
    

方案二:修复前端存储问题(适合必须依赖前端状态的场景)

如果一定要用localStorage或Cookie存储数据,可按以下方式解决现有问题:

解决localStorage未定义报错

getStaticProps在服务端运行,无法访问浏览器的localStorage,所有存储操作必须放在客户端组件的useEffect里:

import { useState, useEffect } from 'react';

export default function VideoDetail() {
  const [selectedCard, setSelectedCard] = useState(null);

  useEffect(() => {
    // 仅在客户端读取localStorage
    const savedCard = localStorage.getItem('selectedCard');
    if (savedCard) {
      setSelectedCard(JSON.parse(savedCard));
    }
  }, []);

  // 保存数据的逻辑也要放在客户端(比如卡片点击时)
  // const handleCardClick = (card) => {
  //   localStorage.setItem('selectedCard', JSON.stringify(card));
  //   router.push('/video-detail');
  // };

  if (!selectedCard) return <div>无数据</div>;
  return <div>{/* 渲染详情内容 */}</div>;
}

修复Cookie存储为%5Bobject%20Object%5D的问题

Cookie只能存储字符串,直接存对象会被转为[object Object](URL编码后就是%5Bobject%20Object%5D),需要先序列化为JSON字符串,读取时再解析:

import cookieCutter from 'cookie-cutter';

// 保存数据到Cookie
const saveCardToCookie = (cardData) => {
  cookieCutter.set('selectedCard', JSON.stringify(cardData), { expires: 1 }); // 设置1天过期
};

// 从Cookie读取数据
const getCardFromCookie = () => {
  const saved = cookieCutter.get('selectedCard');
  return saved ? JSON.parse(saved) : null;
};

// 在客户端组件中使用
export default function VideoDetail() {
  const [selectedCard, setSelectedCard] = useState(null);

  useEffect(() => {
    const card = getCardFromCookie();
    if (card) setSelectedCard(card);
  }, []);

  // ...渲染逻辑
}

总结

优先选择方案一,它契合Next.js的SSR/SSG特性,无需依赖前端存储,刷新、分享链接都能正常工作,也不会出现服务端与客户端环境差异的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 10:27:45