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

NextJS中用Server Action从LocalStorage取Token解决跨端请求问题

核心问题:Server Action 无法直接访问 LocalStorage

Server Action 是运行在服务端的代码,而 LocalStorage 是浏览器客户端专属的存储 API,服务端完全没法直接读取它。所以你想直接在 Server Action 里获取 LocalStorage 的 Token 这条路走不通,得换思路解决。

正确实现方案

1. 客户端取 Token,传递给 Server Action

既然 Server Action 在服务端,只能让客户端把 Token 主动传过去:

  • 在客户端组件(加 'use client' 指令)里读取 LocalStorage 的 Token
  • 调用 Server Action 时,把 Token 作为参数传入

示例代码:

// 客户端组件
'use client';

import { useState, useEffect } from 'react';
import { serverFetchData } from './actions';

export default function ClientComponent() {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    const fetchData = async () => {
      setLoading(true);
      try {
        const token = localStorage.getItem('auth_token');
        const res = await serverFetchData(token);
        setData(res);
      } catch (err) {
        console.error('请求失败:', err);
      } finally {
        setLoading(false);
      }
    };
    fetchData();
  }, []);

  if (loading) return <div>加载中...</div>;
  return <div>{JSON.stringify(data)}</div>;
}

// Server Action(服务端代码,无需'use client')
export async function serverFetchData(token: string | null) {
  if (!token) throw new Error('未提供Token');
  
  const res = await fetch('https://your-api-endpoint.com/data', {
    headers: {
      Authorization: `Bearer ${token}`,
    },
  });

  if (!res.ok) throw new Error('接口请求失败');
  return res.json();
}

2. 解决重复请求与 Suspense 警告

之前的警告是因为你在客户端组件渲染阶段直接创建了未缓存的 Promise,触发了 Suspense 异常。解决方法:

  • 不要在组件渲染时直接调用异步函数,改用 useEffect 触发请求
  • 如果想用 React 的 use 钩子处理异步逻辑,必须配合 Suspense 组件包裹,同时确保请求有合理缓存(比如用框架自带的 fetch 缓存机制)

use 钩子配合 Suspense 的示例:

'use client';

import { Suspense, use } from 'react';
import { serverFetchData } from './actions';

function DataContent() {
  const token = localStorage.getItem('auth_token');
  const data = use(serverFetchData(token));
  return <div>{JSON.stringify(data)}</div>;
}

export default function ClientWrapper() {
  return (
    <Suspense fallback={<div>加载中...</div>}>
      <DataContent />
    </Suspense>
  );
}

如果不想每次手动传 Token,可以把 Token 存在 HttpOnly Cookie 里(安全性更高),服务端能直接从请求头的 Cookie 中读取,无需客户端手动传递:

  • 登录后,后端把 Token 设置为 HttpOnly Cookie
  • Server Action 里直接从请求 Cookie 中获取 Token(以 Next.js 为例)

示例:

// Server Action
import { cookies } from 'next/headers';

export async function serverFetchData() {
  const token = cookies().get('auth_token')?.value;
  if (!token) throw new Error('未登录');
  
  const res = await fetch('https://your-api-endpoint.com/data', {
    headers: {
      Authorization: `Bearer ${token}`,
    },
  });

  if (!res.ok) throw new Error('接口请求失败');
  return res.json();
}

这种方式既省去了客户端传参的麻烦,HttpOnly Cookie 还能避免 XSS 攻击带来的 Token 泄露风险。

内容的提问来源于stack exchange,提问作者Musiur Alam Opu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 17:47:09