Next.js: Fetching Data in Server Components

Updated: December 14, 2023 By: Frienzied Flame Post a comment

Next.js is one of the most popular open-source frameworks for building modern web applications. It offers a rich set of features that makes it a top choice among developers. In this article, we will delve into the intriguing aspect of fetching data in server components using Next.js.

What are Server Components?

Server components are a new addition to the Next.js framework (only available in Next.js 13 and Next.js 14), which enhances its capabilities and provides more flexibility to developers. In essence, server components allow you to write code that runs on the server but can also interact with the client side. This powerful feature can be used to fetch data, perform computations, and access databases, among other things.

The fetch() function

The core mechanism for fetching data in Next.js server components is the fetch() function. The fetch() function provides a powerful and flexible way to retrieve data from APIs. It returns a promise that resolves to the Response object representing the response to the request. This function is available globally, which means you don’t need to import it.

General syntax:

fetch(url, options)

where url is a string that represents the resource you want to fetch, and options is an optional object that can contain various parameters such as method, headers, body, cache, etc. For example:

fetch('https://api.slingacademy.com.com/v1/sample-data/users', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    name: 'John Doe',
    age: 999
  }),
  cache: 'no-cache'
})

This will send a POST request to the https://api.slingacademy.com.com/v1/sample-data/users endpoint with a JSON payload and disable the caching behavior.

The fetch() function returns a promise that resolves to a Response object, which contains information about the status, headers, and body of the response. You can use the .then() or await syntax to handle the promise and access the response data. For example:

fetch('https://api.slingacademy.com')
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error(error))

or:

async function fetchData() {
  try {
    const response = await fetch('https://api.slingacademy.com')
    const data = await response.json()
    console.log(data)
  } catch (error) {
    console.error(error)
  }
}

These will fetch the data from the https://api.slingacademy.com endpoint and log it to the console.

Caching Data with the fetch() function

In Next.js, the fetch() function automatically to cache all requests unless they opt-out. This means that calling fetch() in a static component will have the same effect as using the getStaticProps() function in older versions of Next.js.

Fetching data with cache looks like this:

fetch(API_URL, { cache: 'force-cache' })

The cache: 'force-cache' option (is set by default) ensures that the fetched data is cached until manually invalidated. This is particularly useful for data that does not change often. In case you want to disable caching, just explicitly set cache: 'no-cache'.

A Complete Code Example

Let’s take a closer look at a complete example of how to fetch and render data in Next.js server components. What we’re doing here is getting a list of dummy blog posts from this API endpoint:

https://api.slingacademy.com/v1/sample-data/blog-posts

Here’s the final result:

We’ll use Next.js 14.x with TypeScript and Tailwind CSS. To make sure we have the same starting point, please initialize a brand new Next.js project:

npx create-next-app example

Select TypeScript and Tailwind CSS when you are prompted. After the setup is done, replace all the default code in app/page.tsx with the following:

// app/page.tsx

const API_URL = "https://api.slingacademy.com/v1/sample-data/blog-posts";

interface Blog {
  id: string;
  title: string;
  description: string;
}

export default async function Home() {
  const res = await fetch(API_URL);
  const { blogs } = await res.json();

  return (
    <main className="min-h-screen">
      <div className="p-10 flex flex-col items-start space-y-4">
        <h1 className="text-2xl font-semibold">Sample Blogs</h1>
        {blogs.map((blog: Blog) => (
          <div
            key={blog.id}
            className="py-4 flex flex-col items-start border-t border-blue-300"
          >
            <h1 className="text-lg font-semibold">{blog.title}</h1>
            <p className="text-blue-500">{blog.description}</p>
          </div>
        ))}
      </div> 
    </main>
  );
}

Now get your app up and running:

npm run dev

And then head to http://localhost:3000 to check your work.

You can find more information about the API endpoint we’ve used in the example above on this page: Sample Blog Posts – Public REST API for Practice.

Conclusion

In conclusion, fetching data in server components in Next.js is straightforward and intuitive. With the fetch() function and the ability to cache data, developers can efficiently fetch and manage data in their Next.js applications. As Next.js continues to evolve and improve, we can look forward to even more powerful and flexible data fetching capabilities in the future.

Whether you’re a veteran developer or a newcomer to Next.js, mastering data fetching in server components will certainly level up your Next.js development skills. So why wait? Start fetching data in your Next.js applications today!