如何在 Nextjs 13 中编写一个在服务器和客户端上都能工作的提取器?

How to write a fetcher that works both on the server and the client in Nextjs 13?

提问人:grazdev 提问时间:7/23/2023 更新时间:7/23/2023 访问量:355

问:

我有一个 Nextjs 13 前端(应用程序路由器),它通过 api 与 Laravel 支持的后端进行通信。对于 api 中的身份验证,我使用 Laravel Sanctum(正如 Laravel 为 SPA 推荐的那样):基本上,身份验证的工作原理是在登录后设置两个 cookie(一个会话和一个 CSRF 令牌),然后应该将其附加到所有未来的请求,以及传递 CSRF 令牌的标头。X-Xsrf-Token

要从客户端组件发送请求,我可以执行以下操作:

import cookies from 'js-cookie'

fetch( [url], {
   headers: {
      "Accept": "application/json",
      "Content-Type": "application/json",
      "Origin": [origin],
      "X-Requested-With": "XMLHttpRequest",  
      "X-Xsrf-Token": cookies.get( "XSRF-TOKEN" ),
      // Since we're on the browser, cookies are automatically attached via the 'Cookie' header
   },
   credentials: 'include'
})

如果我从服务器组件发送请求,我可以执行以下操作:

import { cookies, headers } from "next/headers"

fetch( [url], {
   headers: {
      "Cookie": cookies().toString(), // Must attach cookies manually
      "Referer": headers().get( "referer" ) ?? "",
      "X-Xsrf-Token": cookies().get( "XSRF-TOKEN" ).value,
   },
})

两个提取器都可以工作。但是,有时我需要从服务器组件和客户端组件发出相同的请求,因此我想使用这样的单个获取器(这是一个快速而肮脏的示例,只是为了表达我的观点):

import cookies from 'js-cookie'
import { cookies, headers } from "next/headers"

fetch( [url], 
   isServer 
   ?
   {
      headers: {
         "Cookie": cookies().toString(), // Must attach cookies manually
         "Referer": headers().get( "referer" ) ?? "",
         "X-Xsrf-Token": cookies().get( "XSRF-TOKEN" ).value,
      }   
   }
   :
   {
      headers: {
         "Accept": "application/json",
         "Content-Type": "application/json",
         "Origin": process.env.NEXT_PUBLIC_APP_URL,
         "X-Requested-With": "XMLHttpRequest",  
         "X-Xsrf-Token": cookies.get( "XSRF-TOKEN" ),
         // Since we're on the browser, cookies are automatically attached via the 'Cookie' header
      },
      credentials: 'include'
   } 
)

但这会在客户端组件中引发错误,因为 and 函数只能在服务器组件中使用。cookies()headers()

那么,简而言之,我怎样才能编写一个同时适用于服务器和客户端组件的提取器呢?

react-server-components next.js javascript cookie

评论


答:

-1赞 CyberJ 7/23/2023 #1

没错,不能在客户端组件中使用 cookies() 和 headers() 函数,因为它们是服务器函数。这些函数旨在用于服务器组件或服务器操作。

但是,您可以创建一个实用程序函数来检查代码是在服务器还是客户端上运行,然后相应地执行提取。下面是一个基本示例:

import cookies from 'js-cookie'
import { cookies as serverCookies, headers } from "next/headers"

function isServer() {
  return typeof window === 'undefined';
}

async function universalFetch(url, options = {}) {
  if (isServer()) {
    options.headers = {
      ...options.headers,
      "Cookie": serverCookies().toString(),
      "Referer": headers().get("referer") ?? "",
      "X-Xsrf-Token": serverCookies().get("XSRF-TOKEN").value,
    };
  } else {
    options.headers = {
      ...options.headers,
      "Accept": "application/json",
      "Content-Type": "application/json",
      "Origin": process.env.NEXT_PUBLIC_APP_URL,
      "X-Requested-With": "XMLHttpRequest",  
      "X-Xsrf-Token": cookies.get("XSRF-TOKEN"),
    };
    options.credentials = 'include';
  }

  return fetch(url, options);
}

此 universalFetch 函数首先使用 isServer 函数检查它是在服务器还是客户端上运行。如果它位于服务器上,则使用 next/headers 中的 serverCookies 和 headers 函数来设置标头。如果它位于客户端上,则它使用 js-cookie 中的 cookies 函数来获取 XSRF-TOKEN,并将凭据选项设置为“include”。

评论

0赞 NotTheDr01ds 7/24/2023
欢迎回到 Stack Overflow,CyberJ。看起来你已经有一段时间没有发帖了,可能不知道当前的政策,因为你昨天至少有八个答案似乎可能完全或部分是由人工智能(例如,ChatGPT)编写的。请注意,这里不允许发布 AI 生成的内容。如果您使用 AI 工具来协助回答任何问题,我鼓励您将其删除。我们希望您能坚持下去,并通过发布您自己的优质内容继续成为我们社区的重要组成部分。谢谢!
0赞 NotTheDr01ds 7/24/2023
读者应该仔细和批判性地审查这个答案,因为人工智能生成的信息通常包含根本性的错误和错误信息。如果您发现质量问题和/或有理由相信此答案是由 AI 生成的,请留下相应的反馈。