How to Build and Consume an API in Next.js


Gone are the days when you had to create a separate backlink for your website. With the Next.js file-based API directive, you can make your life easier by writing your own API inside a Next.js project.


Next.js is a React definition framework with features that simplify the process of creating production-ready web applications. You will see how to create a REST API in Next.js and consume data from this API on the Next.js page.


Create a Next.js project using create-next-app

You can create a new Next.js project using the Next Application builder CLI. It installs the necessary packages and files to start building the Next.js application.

Run this command in a terminal to create a new Next.js folder called api paths. You may receive a prompt to install create-next-app.

npx create-next-app api-routes

When the command is finished, open the API Paths folder to start creating the API Paths.

API directive in Next.js

API paths run on the server and have many uses such as saving user data in a database or fetching data from an API without raising a CORS policy error.

In Next.js you have to create API paths inside the /pages/api folder. Next.js creates API endpoints for each of the files in this folder. If you add user.js to /pages/api, Next.js will create an endpoint at http://localhost:3000/api/user.

The Next.js API base path contains the following syntax.

export default function handler(req, res) {
res.status(200).json({ name: 'John Doe' })
}

You have to export the wizard’s functionality for it to work.

Create API paths

Create a new file called todo.js in the format /pages/api Folder to add API path for task items.

The mockery of the Todo database

To get the tasks you have to create a GET endpoint. for simplicity. This tutorial uses a set of task stuff instead of a database but feel free to use a database like MongoDB or MySQL.

Create todo items in todo.js in the root folder of your app and then add the following data.

export const todos = [
{
id: 1,
todo: "Do something nice for someone I care about",
completed: true,
userId: 26,
},
{
id: 2,
todo: "Memorize the fifty states and their capitals",
completed: false,
userId: 48,
},
];

These to-do items are from the DummyJSON website, which is a dummy data REST API. You can find the exact data from this DummyJSON todos endpoint.

Next, create the API path in the format /pages/api/todos.js And add a wizard function.

import { todos } from "../../todo";

export function handler(req, res) {
const { method } = req;

switch (method) {
case "GET":
res.status(200).json(todos);
break;
case "POST":
const { todo, completed } = req.body;
todos.push({
id: todos.length + 1,
todo,
completed,
});
res.status(200).json(todos);
break;
default:
res.setHeader("Allow", ["GET", "POST"]);
res.status(405).end(`Method ${method} Not Allowed`);
break;
}
}

This path handles the GET and POST endpoints. It returns all todos for a GET request and adds a todo element to the todo database for a POST request. For other methods, the handler returns an error.

Consuming API paths on the front end

I’ve created an API endpoint that returns a JSON object containing an array from todos.

To consume the API, create a function called fetchTodos that retrieves data from the API endpoint. The function uses the fetch method but you can also use Axios to make API requests. Then call this function when a button is clicked.

import Head from "next/head";
import { useState } from "react";

export default function Home() {
const [todos, settodos] = useState([]);

const fetchTodos = async () => {
const response = await fetch("/api/todos");
const data = await response.json();
settodos(data);
};

return (
<div className={styles.container}>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main>
<button onClick={fetchTodos}>Get todos</button>
<ul>
{todos.map((todo) => {
return (
<li
style={{ color: `${todo.completed ? "green" : "red"}` }}
key={todo.id}
>
{todo.todo}:{todo.completed}.
</li>
);
})}
</ul>
</main>
</div>
);
}

The list in this snippet shows to-do items as they are fetched.

For a POST endpoint, create a new function called saveTodo that makes a POST request to the API. The fetch request stores the new to-do element in the body and returns all to-do elements including the new one. The saveTodo function then stores it in the todos state.

const saveTodo = async () => {
const response = await fetch("/api/todos", {
method: "POST",
body: JSON.stringify(newTodo),
headers: {
"Content-Type": "application/json",
},
});

const data = await response.json();
settodos(data);
};

Next, create a form with a text entry bar to receive the new to-do item. The submit handler function in this model will call the saveTodo function.

import Head from "next/head";
import { useReducer, useState } from "react";
import styles from "../styles/Home.module.css";

export default function Home() {
const [todos, settodos] = useState([]);

const [newTodo, setnewTodo] = useState({
todo: "",
completed: false,
});

const fetchTodos = async () => {
};
const saveTodo = async (e) => {
const response = await fetch("/api/todos", {
method: "POST",
body: JSON.stringify(newTodo),
headers: {
"Content-Type": "application/json",
},
});

const data = await response.json();
settodos(data);
};

const handleChange = (e) => {
setnewTodo({
todo: e.target.value,
});
};

const handleSubmit = (e) => {
e.preventDefault();
saveTodo();
setnewTodo({
todo: '',
});
};

return (
<div className={styles.container}>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main>
<button onClick={fetchTodos}>Get todos</button>


<form onSubmit={handleSubmit}>
<input type="text" onChange={handleChange} value={newTodo.todo} />
</form>
<ul>
{
</ul>
</main>
</div>
);
}

The handler adds a new command to the database each time the user submits the form. Also, this function updates the todos value using the data received from the API which in turn adds the new todo element to the list.

API routing is one of the strengths of Next.js

You have seen how to create and use the Next.js API path. You can now build a full stack application without leaving the Next.js project folder. API routing is one of the many benefits Next.js provides.

Next.js also provides performance improvements such as code splitting, lazy loading, and built-in CSS support. If you are creating a website that should be fast and SEO friendly, then you should consider Next.js.