I’m trying to create an API and fetch data in Next JS 13. I’ve read this question: How do you put api routes in the new app folder of Next.js?
and came up with these:
/src/app/hooks/useLocation.ts
:
export const getUserLocation = () => {
return new Promise((resolve, reject) => {
if ("geolocation" in navigator) {
navigator.geolocation.getCurrentPosition(({coords}) => {
const {latitude, longitude} = coords;
resolve({latitude, longitude});
}, (error) => {
reject(error);
});
} else {
reject("Geolocation not available");
}
});
};
/src/app/location/route.ts
:
import {getUserLocation} from "@/app/hooks/useLocation";
import {NextResponse} from "next/server";
export async function GET() {
const userLocation = getUserLocation();
return NextResponse.json(userLocation);
}
And /src/app/layout.tsx
:
'use server';
import './globals.scss'
interface LayoutProps {
children: React.ReactNode;
}
export default async function RootLayout({ children }: LayoutProps) {
try {
const response = await fetch('/api/location', {
method: 'GET',
cache: 'no-store',
headers: {
'Content-Type': 'application/json'
}
});
if (!response.ok) {
throw new Error('Response error');
};
const responseData = await response.json();
console.log(responseData);
return responseData;
} catch (error) {
console.error('Error fetching data:', error);
};
return (
<html lang="en">
<body>
<main className="flex min-h-screen flex-col items-center justify-between p-24 main">
{children}
</main>
</body>
</html>
)
};
However when running, I got error:
Error fetching data: TypeError: Failed to parse URL from /api/location
at new Request (node:internal/deps/undici/undici:7004:19)
at T (C:projectsxiaohan-dunode_modulesnextdistcompilednext-serverapp-page-experimental.runtime.dev.js:34:233400)
... 13 lines matching cause stack trace ...
at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
[cause]: TypeError [ERR_INVALID_URL]: Invalid URL
Any idea what I’m doing wrong here?
2
Answers
I think you should use the whole URL instead of
/api/location
.Maybe store the route link in an env and use
${API_URL}/api/location
There are few reasons why it won’t work properly,
/src/app/location/route.ts
isn’t proper, keep your API insrc/app/api/folderNameAsAPIName/route.js
. Make api folder & then make a folder inside it with API Name & inside it a route.js/ts file. Read Here Route Handlers https://nextjs.org/docs/app/building-your-application/routing/route-handlers. This is probably the reason why it gives errorError fetching data: TypeError: Failed to parse URL from /api/location
TypeError [ERR_INVALID_URL]: Invalid URL
as there is no api folder insrc/app
./api
folder which is server-side, hence it wont run. (it will show ErrorReferenceError: navigator is not defined
). Read More Navigator: geolocation property'use client'
to do client side operations like events you should add ‘use client’ at top of that component & import it in page. That component will be rendered client side. Read More https://nextjs.org/docs/app/building-your-application/rendering/client-componentsHere’s a small code that I made (it’s in .js you may re-write it in .ts):
Folder Structure :
comp is component folder.
useLocation
hook remains as it is in its current folder.src/app/api/
I made a folderlocation
& inside it a fileroute.js
.This Location API will return
Location API says Hello !!
& when you uncomment those 2 lines above, you will see error :Code inside
src/app/api/location/route.js
Then i made a component inside which i will get Location using that hook & also i made a call to our location api :
Loc Component code :
Note : the api url is
/api/location
is correct as per NextJS convention.Now just import this
<Loc />
component in your page.js to see it run.Output:
In browser :
Recieved from API : Location API says Hello !! Location Hook response : {latitude: someNumbers, longitude:someNumbers } Location Hook response : {latitude:someNumbers , longitude:someNumbers }