#how do I fetch data on the server with the app directory
1 messages · Page 1 of 1 (latest)
In the app directory, you can replace the getServerSideProps function with a simpler API built on top of fetch() and async React Server Components. Instead of using getServerSideProps, you can fetch data directly inside your React components using the fetch() function with the cache option set to no-store. This is similar to how getServerSideProps works in the pages directory.
Here's an example from the App Router Migration Guide (https://nextjs.org/docs/app/building-your-application/upgrading/app-router-migration):
// app/page.tsx
export default async function Page() {
// This request should be refetched on every request.
// Similar to `getServerSideProps`.
const dynamicData = await fetch(`<https://...`,> { cache: 'no-store' });
// ...
return <div>...</div>;
}
By setting the cache option to no-store, you indicate that the fetched data should never be cached, similar to how getServerSideProps works in the pages directory.
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@unkempt olive kapa.ai is still learning and improving, please let us how it did by reacting below
@jolly pilot Well what if I want the fetched data to be cached, but still run on the server?
If I remember correctly, previously on the /pages dir, we could specify a cache header
Let me check the knowledge base for you. One moment! :books:
Yes, you can still cache fetched data when using the app directory. You can set the Cache-Control header in your fetch request to cache the data. For example, you can use the stale-while-revalidate strategy, which serves stale content while the cache is refreshed in the background.
Here's an example of how to set the Cache-Control header in a Next.js API route:
// pages/api/user.js
export default function handler(req, res) {
res.setHeader('Cache-Control', 's-maxage=86400');
res.status(200).json({ name: 'John Doe' });
}
In your React component, you can use the fetch() function with the cache option set to force-cache for caching similar to getStaticProps:
// app/page.tsx
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 dynamicData = await fetch(`<https://...`,> { cache: 'force-cache' });
// ...
return <div>...</div>;
}
For more information on caching, refer to the Next.js documentation on caching (https://nextjs.org/docs/app/building-your-application/data-fetching/caching) and the Vercel guide on reducing serverless execution usage (https://vercel.com/guides/how-can-i-reduce-my-serverless-execution-usage-on-vercel).
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@unkempt olive kapa.ai is still learning and improving, please let us how it did by reacting below
@jolly pilot If I set the cache option to no-store, will the fetch be run on the server or client
Let me check the knowledge base for you. One moment! :books:
If you set the cache option to no-store, the fetch will be run on the server when using Next.js Server Components. Here's an example:
// app/page.tsx
export default async function Page() {
// This request should be refetched on every request.
// Similar to `getServerSideProps`.
const dynamicData = await fetch(`<https://...`,> { cache: 'no-store' });
// ...
return <div>...</div>;
}
In this example, the fetch request will be executed on the server, and the data will not be cached. This behavior is similar to using getServerSideProps in the pages directory.
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@unkempt olive kapa.ai is still learning and improving, please let us how it did by reacting below
@jolly pilot now instead of simply fetching data, how can I access my database on the server?
Let me check the knowledge base for you. One moment! :books:
To access your database on the server, you can use native JavaScript patterns for common data that multiple Server Components need to access. For example, you can create a module to share a database connection across multiple components. Here's an example from the React Essentials documentation (https://nextjs.org/docs/getting-started/react-essentials#sharing-data-between-server-components):
Create a module to share the database connection:
// utils/database.ts
export const db = new DatabaseConnection();
Then, import the shared database connection in your components:
// app/users/layout.tsx
import { db } from '@utils/database';
export async function UsersLayout() {
let users = await db.query();
// ...
}
// app/users/[id]/page.tsx
import { db } from '@utils/database';
export async function DashboardPage() {
let user = await db.query();
// ...
}
In these examples, both the layout and page components need to make database queries. They share access to the database by importing the @utils/database module. This JavaScript pattern is called global singletons.
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@unkempt olive kapa.ai is still learning and improving, please let us how it did by reacting below
@jolly pilot correct me if I'm wrong. You're telling me that if I set a function to 'async' it will run on the server
Let me check the knowledge base for you. One moment! :books:
I apologize for the confusion earlier. I misunderstood your question. The async keyword itself doesn't determine whether the function runs on the server or the client. It only indicates that the function contains asynchronous operations.
To run a function on the server, you can create an API route in the pages/api directory. API routes are server-side functions that can be called from the client. Here's an example:
// pages/api/data.js
export default async function handler(req, res) {
// Fetch data from your database or an external API
const data = await fetchData();
// Send the data as a JSON response
res.status(200).json(data);
}
Then, in your component, you can fetch data from the API route:
// app/page.tsx
export default function Page() {
const [data, setData] = useState(null);
useEffect(() => {
async function fetchData() {
const res = await fetch('/api/data');
const data = await res.json();
setData(data);
}
fetchData();
}, []);
// Render the component with the fetched data
return <div>{data ? JSON.stringify(data) : 'Loading...'}</div>;
}
In this example, the fetchData function in the API route (pages/api/data.js) runs on the server, while the fetch call in the component (app/page.tsx) runs on the client.
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@unkempt olive kapa.ai is still learning and improving, please let us how it did by reacting below
@jolly pilot so the only way you can fetch info and return values in the /app directory is using the /api route right? As there is no equivalent of getServerSideProps in the /app directory
Let me check the knowledge base for you. One moment! :books: