Reputation: 446
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.
Upvotes: 28
Views: 37274
Reputation: 1
I was just working on this today and I had the problem where I couldn't use GetServerSideProps on the app/page.tsx file.
So looking into it, I stumbled accross this documentation:
https://nextjs.org/docs/app/building-your-application/data-fetching/fetching
Look at the first example, the key is to insert the "async" into the "export default async function Page() (...)
" for it to properly work. It worked very well for me for server side loading and display of data.
Upvotes: 0
Reputation: 46161
Methods like getServerSideProps
and getStaticProps
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
directory (used when you answer yes to the last question shown in the below image) we have 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:
// 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();
// ...
}
UPDATE: In nextjs 15, the fetch default option for cache is no-store
.
Upvotes: 32
Reputation: 1
see: app router migration
export default async function Page() {
// 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 <div>...</div>
}
Upvotes: 0
Reputation: 361
In app directory you cannot use getServerSideProps
, getStaticProps
, getInitialProps
like methods for data fetching. Instead of this with server component you can make component it self async and fetch data in component body directly. Further more you can pass the data to client component for rendering service.
export async function getData(){
const res = await fetchData();
const data = res.json()
return data
}
Now you can call this async function in your main component
export async function(){
const data = await getData()
return (<ClientComponent data />)
}
Upvotes: 2
Reputation: 10502
This StackOverFlow question (Can't use GetStaticProp in Next.js 13) was closed as a duplicate of this question.
To help rookies like me:
You can't use getStaticProps in Nextjs 13 (using App Router).
The new way is to just use fetch. You can read more about fetch here.
async function getArtist(username: string) {
const res = await fetch(`https://api.example.com/artist/${username}`)
return res.json()
}
This image compares the old and new way of doing things. image source
Because the new default is to cache all fetch requests (unless they opt out) calling fetch in a static component has the same effect as getStaticProps
. You can read more about Static Data Fetching here.
So to be clear this normal fetch request:
//Similar to 'getStaticProps' when used in a static rendering component
fetch(API_URL)
is the same as this 'force-cache' request:
//This request would be cached until manually invalidated.
//Similar to 'getStaticProps'
//Use this type of fetching for data that does not change often.
fetch(API_URL, { cache: 'force-cache' })
More info about the default caching here.
Why did you want to use getStaticProps in the first place?
To help the rookies, who find getStaticProps
in a tutorial and find there way here, the reason you want to use getStaticProps
is you want to render a page once, and then send that page to every user.
This makes your page faster, send less code to your users, and is better for SEO etc.
But what if you need to get some data to render that page once? Before Nextjs 13 you would use getStaticProps
.
Now you fetch
in a static component. The effect is the same.
And that effect is, once (at build time when you deploy your project) Nextjs will go get some data, then use that data to render a page, and then send that pre-rendered page to everyone who needs it.
If you need to statically generate a bunch of pages using dynamic routes, the generateStaticParams
function can be used to generate routes at build time instead of on-demand at request time for dynamic routes. info here.
For rookies, if you don't know what dynamic routes are, just use fetch
. :)
Upvotes: 17