Algobook
- The developer's handbook
mode-switch
back-button
Buy Me A Coffee
Fri Jun 09 2023

Fetch data from an API in your Next.js page in App router

As the owner of this website, I care a lot about my SEO performance and my wish is of course that more people will find my website and read my articles and use my free APIs and so on. Hence, I made the decision to try out Next.js and make my application server rendered, which is one of the biggest recommendations out there when it comes to improving the SEO. There was just this small little detail - I have never worked a minute with Next.js, and I was throwing myself out in the unknown.

The transition from a regular create-react-app to a Next.js app went quite smooth, I had it up and running after a few days of work - and my goal now is to create small tutorials about the problems that I stumbled on as a new Next.js dev, and to share it with other people that might find themselves in the same situation. So today, I will share how we can fetch data in our page.tsx that is located in the app folder.

Problem

So, the problem is, that we want the page to come from the server already rendered, so that we don't need to call the API for example in the client and upset the crawlers that will index our page.

In my case, I had a page that were fetching data in a useEffect and displayed a loading spinner while we were waiting for the response to get back with the content. And now I wanted it to do all that, but on the server side and get back to the client rendered.

Consider the page looked something like this before Next.js entered the application:

export const BlogPage = () => { const [isLoading, setLoading] = useState(true); const [blogText, setBlogText] = useState(null); useEffect(() => { const fetchData = async () => { const response = await fetch("https://blogapi.com"); const data = await response.text(); setBlogText(blogText); setLoading(false); }; fetchData(); }, []); if (isLoading) { return <div>Loading...</div>; } return <div>{blogText}</div>; };

So when the page is mounted, we call our API and when we get the response we are setting the states and show the blog text etc. And this is a perfectly normal way of doing it when we are client side rendering our page, but when we are using Next.js and want the content to be ready on the page request, we need to do stuff differently.

Solution

I was placing all my pages and routes in the app folder, and for what I could understand it works differently than in the pages folder, where we can specify like getStaticParams and initialProps etc, to fetch data for the components to use. But there was a smooth way for me to achieve exactly what I wanted.

The solution is, to make the page async and then do the API call directly in the page, and it will sort it out for us.

Example:

export default async function BlogPage() { const response = await fetch("https://blogapi.com"); const blogText = await response.text(); return <div>{blogText}</div>; }

And that's it. Now the page will get back to us rendered and everything. This will also work fine with the use client directive. However, there seems to be a little catch though. There are two prerequisites:

  • TypeScript needs to be version 5.1.3 or higher
  • And @types/react 18.2.8 or higher

So make sure to update them accordingly in order for it to work.

Summary

In this guide, we took a look at how we can fetch data directly in our page so that it will come back rendered from the server so we can get rid of the client side fetching and utilize the power of Next.js.

I really hope you enjoyed this guide, and if you have any feedback we love to hear from you. Send an email from our contact page.

Have an amazing day!

signatureFri Jun 09 2023
See all our articles