Question
I am working on a Django Rest Framework with Next.js, and I am getting stuck
with fetching data from the API. I have data in this url
http://127.0.0.1:8000/api/campaigns
and when I visit the url I see the data.
The problem is when I fetch and console the data with Next.js, I get
undefined
. Also when I try mapping the data, I get the error:
Unhandled Runtime Error
Error: Cannot read properties of undefined (reading 'map')
Here is my Index.js
file where the data fetching is done:
import React from 'react'
export default function Index ({data}) {
console.log(data)
return (
<div>
<main>
<h1>Available Campaigns</h1>
{data.map((element) => <div key={element.slug}>
<div>
<div>
<img src={element.logo} height={120} width={100} alt="image" />
</div>
<div></div>
</div>
</div>)}
</main>
</div>
);
}
export async function getStaticProps() {
const response = await fetch("http://127.0.0.1:8000/api/campaigns");
const data = await response.json();
return {
props: {
data: data
},
}
}
Here is a screenshot of the data I am getting when I visit the URL:
Here is the file structure for the Next.js app inside the front end:
Also, note that I am using the latest version of Next.js. Any help will be highly appreciated. Thanks.
Answer
Methods like [getServerSideProps
](https://nextjs.org/docs/pages/building-
your-application/data-fetching/get-server-side-props) and
[getStaticProps
](https://nextjs.org/docs/pages/building-your-
application/data-fetching/get-static-props) are for fetching data on the
server but they only work for page components inside the
pages
folder
(the initial way of setting up routes in Next.js).
Since Next.js 13, in the [app
](https://nextjs.org/docs/getting-
started/project-structure) directory (used when you answer yes to the last
question shown in the below image) we have [Server
Components](https://nextjs.org/docs/getting-started/react-essentials#server-
components), where you can fetch data directly in the component body as shown
in the below code snippet (please read the comments):
/*
If you want to access headers or cookies while fetching data,
you can use these functions:
*/
import { cookies, headers } from "next/headers";
/*
If the below component is the default export of a `page.js` and you are using
dynamic routes, slugs will be passed as part of `params`, and
query strings are passed as part of `searchParams`.
*/
export default async function Component({ params, searchParams }) {
/*
This request should be cached until manually invalidated.
Similar to `getStaticProps`.
`force-cache` is the default and can be omitted.
*/
const staticData = await fetch(`https://...`, { cache: "force-cache" });
/*
This request should be refetched on every request.
Similar to `getServerSideProps`.
*/
const dynamicData = await fetch(`https://...`, { cache: "no-store" });
/*
This request should be cached with a lifetime of 10 seconds.
Similar to `getStaticProps` with the `revalidate` option.
*/
const revalidatedData = await fetch(`https://...`, {
next: { revalidate: 10 },
});
return "...";
}
That has been said, you can get data without fetch()
, using any library, or
even directly talking to your database with an ORM, in which case you can use
[Route Segment Config](https://nextjs.org/docs/app/api-reference/file-
conventions/route-segment-config):
// layout.js OR page.js OR route.js 👈🏽
import prisma from "./lib/prisma";
/*
Keep one of the possibilities shown below (there are more on the doc),
depending on your needs.
*/
export const revalidate = 10; // If you want to revalidate every 10s
// OR
export const dynamic = "force-dynamic"; // If you want no caching at all
// ...
async function getPosts() {
const posts = await prisma.post.findMany();
return posts;
}
export default async function Page() {
const posts = await getPosts();
// ...
}