Why does a 204 response to a fetch() in a React Server Component throw a TypeError (Invalid response status code)?

huangapple go评论90阅读模式
英文:

Why does a 204 response to a fetch() in a React Server Component throw a TypeError (Invalid response status code)?

问题

以下是翻译好的内容:

考虑以下简单的 Next.js 应用:https://codesandbox.io/p/sandbox/next-js-app-router-1bvd7d?file=README.md

我们有一个 API 路由(/api/hello):

export default function handler(req, res) {
  res.status(204).end();
}

还有一个 React 服务器组件(RSC)中的 fetch:

export default async function Home() {
  let res;
  try {
    res = await fetch("https://rpvequ-3000.csb.app/api/hello");
    console.log("res.status", res.status);
    console.log("res", res);
  } catch (error) {
    console.log("res in error", res);
    console.log("error", error);
  }
  return (
    <main>
      <p>HELLO WORLD</p>
    </main>
  );
}

fetch 抛出以下错误消息:

TypeError: Response constructor: Invalid response status code 204

如果我们将 HTTP 响应从 204 更改为 202,例如,fetch 就不再抛出错误。

为什么我们在状态码为 204 时会收到错误?有没有办法在 RSC 中检查响应是否为 204,以便我们可以根据需要进行处理?


附注:

在 React 客户端组件中的相同 fetch() 由于某种原因 不会 抛出错误:

"use client";
import React, { useEffect } from "react";

const ClientComp = ({ children }) => {
  useEffect(() => {
    let res;
    (async () => {
      try {
        res = await fetch("http://localhost:3000/api/hello");
        console.log("res.status", res.status);
        console.log("res", res);
      } catch (error) {
        console.log("res in error", res);
        console.log("error", error);
      }
    })();
  }, []);

  return <div>{children}</div>;
};

export default ClientComp;

换句话说,仅当由 React 服务器组件 接收时,具有状态码 204 的 HTTP 响应才会抛出错误,而不会出现在 React 客户端组件 中。

英文:

Consider the following simple Next.js app: https://codesandbox.io/p/sandbox/next-js-app-router-1bvd7d?file=README.md

We have a API route (/api/hello):

export default function handler(req, res) {
  res.status(204).end();
}

And a fetch in a React Server Component (RSC):

export default async function Home() {
  let res;
  try {
    res = await fetch(&quot;https://rpvequ-3000.csb.app/api/hello&quot;);
    console.log(&quot;res.status&quot;, res.status);
    console.log(&quot;res&quot;, res);
  } catch (error) {
    console.log(&quot;res in error&quot;, res);
    console.log(&quot;error&quot;, error);
  }
  return (
    &lt;main&gt;
      &lt;p&gt;HELLO WORLD&lt;/p&gt;
    &lt;/main&gt;
  );
}

The fetch throws the following error message:

> TypeError: Response constructor: Invalid response status code 204

If we change the HTTP response from 204 to 202, for instance, the fetch no longer throws an error.

How come we get an error with 204? Is there any way to check if the response was 204 inside the RSC, so we can handle it as needed?


PS: If you are testing it in the Codesandbox or otherwise, remember to delete the .next folder every time you restart the dev server (otherwise fetch() just uses what was cached last time).


Side Note:

The same fetch() in a React Client Component does for some reason not throw an error:

&quot;use client&quot;;
import React, { useEffect } from &quot;react&quot;;

const ClientComp = ({ children }) =&gt; {
  useEffect(() =&gt; {
    let res;
    (async () =&gt; {
      try {
        res = await fetch(&quot;http://localhost:3000/api/hello&quot;);
        console.log(&quot;res.status&quot;, res.status);
        console.log(&quot;res&quot;, res);
      } catch (error) {
        console.log(&quot;res in error&quot;, res);
        console.log(&quot;error&quot;, error);
      }
    })();
  }, []);

  return &lt;div&gt;{children}&lt;/div&gt;;
};

export default ClientComp;

In other words, a HTTP response with status code 204 only throws an error when received by a fetch() in a React Server Component, not in a React Client Component.

答案1

得分: 1

这是Next.js中的一个错误,已在此PR https://github.com/vercel/next.js/pull/48354 中修复。

英文:

This was a bug in Next.js and it was fixed in this PR https://github.com/vercel/next.js/pull/48354

huangapple
  • 本文由 发表于 2023年4月4日 06:15:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/75924132.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定