In this article, we will discuss how to call internal APIs in the Next JS application. We will create new internal APIs, define routes, fetch data and test by using the Jest and supertest tools.
We will discuss how to make internal API calls using the getStaticProps or getServerSideProps hooks inside the component/page. Most importantly we will also discuss handling errors while making the API calls and how to prevent re-rendering when calling the API route from a page.
[lwptoc]
What are Internal APIs?
Internal APIs are also known as server APIs or back-end APIs which are the endpoints that reside within your own application and stay on the same server. They serve the purpose of fetching and manipulating the data required for your application.
Let’s move ahead to create internal APIs to test the data fetching from application’s own server with examples:
Setting Up a Next.js Project
First, we will create a new Next js application by executing the below command in your terminal:
npx create-next-app my-next-app
cd my-next-app
Creating an Internal API Route
Internal APIs are implemented as API routes in Next js which are special files placed inside the pages/api directory. Let’s create a simple internal API route for fetching a list of products.
Create a new API route file:
For creating a new API, create a new file products.js under pages/api directory.
touch pages/api/products.js
Define your API route:
Thereafter, in the products.js file, we will define the API route logic as shown below:
// pages/api/products.js
export default function handler(req, res) {
const products = [
{ id: 1, name: 'Product 1' },
{ id: 2, name: 'Product 2' },
{ id: 3, name: 'Product 3' },
];
res.status(200).json(products);
}
In the above file, we are exporting a function called handler
that responds with a JSON array of products when the route will be accessed.
Access the API route:
Now, we can access this API route which can be a GET request to /api/products
. You can do this from your React components using standard fetch or axios requests.
Fetching Data from the Internal API
Now, we have created our own Internal API route and are ready to be used to fetch data in Next js pages or components. Let’s have a look at an example to fetch and display the list of products:
// pages/index.js
import React, { useEffect, useState } from 'react';
function HomePage() {
const [products, setProducts] = useState([]);
useEffect(() => {
async function fetchProducts() {
const response = await fetch('/api/products');
const data = await response.json();
setProducts(data);
}
fetchProducts();
}, []);
return (
<div>
<h1>Products</h1>
<ul>
{products.map((product) => (
<li key={product.id}>{product.name}</li>
))}
</ul>
</div>
);
}
export default HomePage;
In this code, we have used the useState
and useEffect
hooks to fetch the data when the component mounts. We then map over the products and display them in a list. Here we used the Javascript fetch method to make HTTP call but you can also use the Axios library to perform HTTP operations.
Testing Your Internal API
Testing plays a crucial role in the API development process. Next js provides good support for testing internal APIs. In this section, we will discuss how to use tools like Jest and Supertest for the same.
Let’s follow these simple steps to set test for your internal API routes:
Install the necessary packages
First, we will install the required packages including Jest and supertest by executing below commands:
npm install --save-dev jest supertest
Create a test file
Now, create a new file products.test.js under this directory pages/api:
touch pages/api/products.test.js
Write your test
In the products.test.js file, write a test for your API route. Here is the basic example:
// pages/api/products.test.js
import request from 'supertest';
import handler from './products';
describe('/api/products', () => {
it('responds with a list of products', async () => {
const response = await request(handler).get('/');
expect(response.statusCode).toBe(200);
expect(response.body).toHaveLength(3); // Assuming you have 3 products
});
});
This test will trigger a GET request to the API route and checks the response status code also the length of the returned array.
Run the tests
Next, you can now run tests using Jest:
npm test
How to Call API route from getStaticProps or getServerSideProps?
We can call an API route from the getStaticProps
or getServerSideProps
functions in a page component. These functions are used for data fetching and server-side rendering.
Calling an API from getStaticProps
Here we are using the fetch
API to make a request to our internal API route /api/products and then pass the fetched data as a prop to the page component:
// pages/index.js
import React from 'react';
function HomePage({ products }) {
// Your component code here
}
export async function getStaticProps() {
const res = await fetch('http://localhost:3000/api/products');
const products = await res.json();
return {
props: {
products,
},
};
}
export default HomePage;
Calling an API from getServerSideProps
In this example, we have used the getServerSideProps
function to fetch data from the API route based on the id
parameter:
// pages/product/[id].js
import React from 'react';
function ProductPage({ product }) {
// Your component code here
}
export async function getServerSideProps({ params }) {
const { id } = params;
const res = await fetch(`http://localhost:3000/api/products/${id}`);
const product = await res.json();
return {
props: {
product,
},
};
}
export default ProductPage;
How to Handle Errors while Calling Internal API Routes?
Error handling is very important while calling the internal API routes in Next js for a good user experience. We can use the try-catch block to handle errors gracefully. If an error occurs, we pass it as a prop to the component for rendering.
// pages/index.js
import React from 'react';
function HomePage({ products, error }) {
if (error) {
return <div>Error: {error.message}</div>;
}
// Your component code here
}
export async function getStaticProps() {
try {
const res = await fetch('http://localhost:3000/api/products');
if (!res.ok) {
throw new Error('Failed to fetch data');
}
const products = await res.json();
return {
props: {
products,
},
};
} catch (error) {
return {
props: {
error,
},
};
}
}
export default HomePage;
How to Call API Route from getInitialProps?
In older versions of Next.js, you could use getInitialProps
for data fetching. Here’s an example of how to call an API route using getInitialProps
:
// pages/index.js
import React from 'react';
function HomePage({ products }) {
// Your component code here
}
HomePage.getInitialProps = async () => {
const res = await fetch('http://localhost:3000/api/products');
const products = await res.json();
return {
products,
};
};
export default HomePage;
Please note that getInitialProps
is considered legacy in Next.js 10 and later versions, and you should prefer using getStaticProps
or getServerSideProps
for data fetching.
How to Avoid Re-rendering when calling an API route?
We can use the useSWR library to prevent unnecessary re-renders for data fetching. It allows to fetch data on the client side and manages caching to prevent re-fetching.
How to Use useSWR
First, install swr
by triggering below command:
npm install swr
Now, you can use useSWR
in your component:
// pages/index.js
import React from 'react';
import useSWR from 'swr';
function HomePage() {
const { data: products, error } = useSWR('/api/products', fetch);
if (error) {
return <div>Error: {error.message}</div>;
}
if (!products) {
return <div>Loading...</div>;
}
// Your component code here
}
export default HomePage;
In above example, useSWR
fetches data from the /api/products route on the client side, and it handles caching and re-validation for you. This helps prevent unnecessary re-renders while ensuring the data is always up to date.
Conclusion
In the above-detailed tutorial, we discussed how to set the Internal API route, trigger the call and fetch data using multiple ways with the help of getStaticProps or getServerSideProps. We also discussed how to perform testing of internal APIs and handle errors. In the end, we discussed how to implement caching by using the useSWR package to prevent unnecessary API calls and fetch data from the cached data.
Hope this will be helpful.
Leave a Reply