admin管理员组文章数量:1319467
I am making a NextJS React application and trying to fetch data from my server using this line:
let data = await fetch('/api/getAllAlumniInfoList').then(res => res.json())
When I run the server using next dev
, everything works fine. But when I try to build the application for production using next build
I get this error:
(node:173544) ExperimentalWarning: The Fetch API is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
node:internal/deps/undici/undici:5491
throw new TypeError("Failed to parse URL from " + input, { cause: err });
^
TypeError: Failed to parse URL from /api/getAllAlumniInfoList
at new Request (node:internal/deps/undici/undici:5491:19)
at Agent.fetch2 (node:internal/deps/undici/undici:6288:25)
... 4 lines matching cause stack trace ...
at Wc (/app/goatconnect/goatconnect/node_modules/react-dom/cjs/react-dom-server.browser.production.min.js:68:44)
at Zc (/app/goatconnect/goatconnect/node_modules/react-dom/cjs/react-dom-server.browser.production.min.js:70:253)
at Z (/app/goatconnect/goatconnect/node_modules/react-dom/cjs/react-dom-server.browser.production.min.js:76:89)
at Zc (/app/goatconnect/goatconnect/node_modules/react-dom/cjs/react-dom-server.browser.production.min.js:70:481) {
[cause]: TypeError [ERR_INVALID_URL]: Invalid URL
at new NodeError (node:internal/errors:393:5)
at URL.onParseError (node:internal/url:564:9)
at new URL (node:internal/url:644:5)
at new Request (node:internal/deps/undici/undici:5489:25)
at Agent.fetch2 (node:internal/deps/undici/undici:6288:25)
at Object.fetch (node:internal/deps/undici/undici:7125:20)
at fetch (node:internal/process/pre_execution:214:25)
at onSearch (/app/goatconnect/goatconnect/.next/server/pages/coach/alumniView.js:75:30)
at PlayersView (/app/goatconnect/goatconnect/.next/server/pages/coach/alumniView.js:103:9)
at Wc (/app/goatconnect/goatconnect/node_modules/react-dom/cjs/react-dom-server.browser.production.min.js:68:44) {
input: '/api/getAllAlumniInfoList',
code: 'ERR_INVALID_URL'
}
}
Another strange thing about this error is I have different pages with the same exact structure using the same logic that work fine and the piler does not plain about. I am not sure what could be causing this API route to not be recognized correctly.
I have tried to use the NextJS provided hook useSWR
which works in a lot of other instances but this specific use case is for a database search so using a hook causes a infinite loop when the page is updated with the results of the API call.
I am making a NextJS React application and trying to fetch data from my server using this line:
let data = await fetch('/api/getAllAlumniInfoList').then(res => res.json())
When I run the server using next dev
, everything works fine. But when I try to build the application for production using next build
I get this error:
(node:173544) ExperimentalWarning: The Fetch API is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
node:internal/deps/undici/undici:5491
throw new TypeError("Failed to parse URL from " + input, { cause: err });
^
TypeError: Failed to parse URL from /api/getAllAlumniInfoList
at new Request (node:internal/deps/undici/undici:5491:19)
at Agent.fetch2 (node:internal/deps/undici/undici:6288:25)
... 4 lines matching cause stack trace ...
at Wc (/app/goatconnect/goatconnect/node_modules/react-dom/cjs/react-dom-server.browser.production.min.js:68:44)
at Zc (/app/goatconnect/goatconnect/node_modules/react-dom/cjs/react-dom-server.browser.production.min.js:70:253)
at Z (/app/goatconnect/goatconnect/node_modules/react-dom/cjs/react-dom-server.browser.production.min.js:76:89)
at Zc (/app/goatconnect/goatconnect/node_modules/react-dom/cjs/react-dom-server.browser.production.min.js:70:481) {
[cause]: TypeError [ERR_INVALID_URL]: Invalid URL
at new NodeError (node:internal/errors:393:5)
at URL.onParseError (node:internal/url:564:9)
at new URL (node:internal/url:644:5)
at new Request (node:internal/deps/undici/undici:5489:25)
at Agent.fetch2 (node:internal/deps/undici/undici:6288:25)
at Object.fetch (node:internal/deps/undici/undici:7125:20)
at fetch (node:internal/process/pre_execution:214:25)
at onSearch (/app/goatconnect/goatconnect/.next/server/pages/coach/alumniView.js:75:30)
at PlayersView (/app/goatconnect/goatconnect/.next/server/pages/coach/alumniView.js:103:9)
at Wc (/app/goatconnect/goatconnect/node_modules/react-dom/cjs/react-dom-server.browser.production.min.js:68:44) {
input: '/api/getAllAlumniInfoList',
code: 'ERR_INVALID_URL'
}
}
Another strange thing about this error is I have different pages with the same exact structure using the same logic that work fine and the piler does not plain about. I am not sure what could be causing this API route to not be recognized correctly.
I have tried to use the NextJS provided hook useSWR
which works in a lot of other instances but this specific use case is for a database search so using a hook causes a infinite loop when the page is updated with the results of the API call.
-
Are you sure that it's a valid url
/api/getAllAlumniInfoList
? – Konrad Commented Nov 21, 2022 at 18:15 -
@Konrad yes, the fetch works fine when I run the application using
next dev
. The client can request data from the server at that route. – Hmkyriacou Commented Nov 21, 2022 at 18:26 -
Can you please show how do you use other
fetch
s that don't throw an error? – Konrad Commented Nov 21, 2022 at 18:27 -
@Konrad Sure, here is one example:
let data = await fetch('/api/getAllPlayerInfoList').then(res => res.json())
. It is a different route, but the page that it is on is doing the exact same logic for the "player list" rather than the "alumni list" where I am getting the error. – Hmkyriacou Commented Nov 21, 2022 at 18:29 -
Are you calling the endpoint on the client-side in all cases? Also, have you tried deleting the
.next
folder? – ivanatias Commented Nov 21, 2022 at 19:50
4 Answers
Reset to default 6Why does the error happen ?
The fetch
api used by Next.js is ambiguous and depends on the context where it is executed :
- in the browser, it will refer to the fetch api from
window
- on the server (and build phase), it will refer to the fetch api from
node
As a consequence, you will need to disambiguate fetch
.
If you do not want to disambiguate fetch, then you will have to use only valid URL
s (in other words: no relative paths).
How to disambiguate fetch
There are different ways to do it : use a library, use a facade or make it explicit (see below).
Be aware that if you choose to make it explicit, you will have to separate client side code from server side code. If that still fits your needs, then :
- client side, use
window.fetch
- server side, import node-fetch explicitly :
import * as nodeFetch from "node-fetch"; // use nodeFetch instead of fetch
EDIT: Node.js >= 21 includes fetch API natively (import node:fetch
to use it).
In a ponent
Using ponentDidMount
, the code will be executed only in the browser (implies that your data will be rendered client side).
I think the actual reason for the original poster's error message is that the fetch
call was not done inside a useEffect
hook. Calling fetch
through useEffect
solved a nearly identical problem in my case, and it is what the documentation proscribes:
https://nextjs/docs/app/building-your-application/data-fetching/fetching#fetching-data-on-the-client
They do point out in the documentation that fetching data client-side is generally not remended, and if it is still needed, they remend using a library rather than direct fetch
calls. But if fetch
is used client-side, it must be called from useEffect
.
Doing so makes the error message from next build
go away, and while it is clearly preferable with server-side data fetching in production scenarios, client-side fetching can be useful when prototyping and testing new ponents, especially if they need to be made available to testers from a simple static web server.
I solved this problem by using the URL constructor.
const link = new URL(`${process.env.NEXTAUTH_URL}/api/addviewer`);
const res:any = await fetch(link, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(formData),
});
useSWR is a good option but for fetch i would remend using unfecth as a fetcher for useSWR. Worked without issues for me.
import fetch from 'unfetch'
import useSWR from 'swr'
function YourComponent() {
const { data, error } = useSWR('/api/getAllAlumniInfoList', fetch)
if (error) return <div>failed to load</div>
if (!data) return <div>loading...</div>
return <div>hello {data.name}!</div>
}
An update with search input, useSWR and no infinite loop:
import { ChangeEvent, useCallback, useState } from "react";
import styles from "../styles/Home.module.css";
import fetch from "unfetch";
import useSWR from "swr";
import { debounce } from "lodash";
const fetcher = (url: string) => fetch(url).then((res) => res.json());
export default function Home() {
const [value, setValue] = useState<string>("");
const { data = [], error } = useSWR(
value ? `/api/user/${value}` : null,
fetcher,
{
fallbackData: [],
}
);
const onChange = debounce(
useCallback(
(e: ChangeEvent<HTMLInputElement>) => setValue(e.target.value),
[value]
),
500
);
if (error) {
return <div>An error occured</div>;
}
return (
<div className={styles.container}>
<input onChange={onChange} />
{data?.map((e: any) => (
<div key={Math.random()}>{e.name}</div>
))}
</div>
);
}
IMPORTANT: value cannot be passed to input. Just pass onChange method.
On API side with fake data, filepath /pages/api/user/[name].ts
:
import type { NextApiRequest, NextApiResponse } from "next";
type Data = {
name: string;
};
const data: Array<Data> = [
{ name: "John Doe" },
{ name: "Miss Pierce Bogisich" },
{ name: "Beaulah Tillman" },
{ name: "Aracely Hessel" },
{ name: "Margret Berge" },
{ name: "Hailee Macejkovic" },
{ name: "Lazaro Feeney" },
{ name: "Gennaro Rutherford" },
{ name: "Ian Hackett" },
{ name: "Sonny Larson" },
{ name: "Dr. Liza Wolf" },
];
export default function handler(
req: NextApiRequest,
res: NextApiResponse<Array<Data>>
) {
const {
query: { name },
} = req;
console.log(name);
res
.status(200)
.json(
data.filter((e) =>
e.name.toLowerCase().includes(`${name?.toString().toLowerCase()}`)
)
);
}
本文标签:
版权声明:本文标题:javascript - NextJS fetch() throws invalid URL error when running next build but next dev works fine - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742062231a2418641.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论