NextJS lets us create backend API routes with great ease. We can call the API endpoints using normal JavaScript fetch API. However, we can also utilize these API routes with server side rendering. In this post, we will learn how to create NextJS GET API routes and use it for static server-side rendering.

This post follows on from our introduction to NextJS API Routes. Therefore, I will recommend you to go through that post before this one.

1 – Creating a NextJS GET API Route

As we already know, in NextJS all API related code is kept within a special folder api inside the pages folder of our project. When we have the api folder, NextJS automatically tries to expose the functionality as an API.

Assuming that we are creating an application to collect and display feedback, below is our API code.

import fs from 'fs';
import path from 'path';

export function buildFeedbackPath() {
    return path.join(process.cwd(), 'data', 'feedback.json');
}

export function extractFeedbackData() {
    const filePath = buildFeedbackPath()
    const fileData = fs.readFileSync(filePath);
    return JSON.parse(fileData);
}

function handler(req, res) {
    if (req.method === 'POST') {
        const email = req.body.email;
        const feedbackText = req.body.text;

        const newFeedback = {
            id: new Date().toISOString(),
            email: email,
            text: feedbackText
        };

        //store the feedback data in a file
        const filePath = buildFeedbackPath()
        const data = extractFeedbackData(filePath);
        data.push(newFeedback);
        fs.writeFileSync(filePath, JSON.stringify(data));
        res.status(201).json({ message: 'Feedback logged', feedback: newFeedback });
    } else {
        const filePath = buildFeedbackPath()
        const data = extractFeedbackData(filePath);
        res.status(200).json({ feedback: data });
    }
}

export default handler;

As you can see, we have a common handler function. Within this function, we handle the scenario for a POST request where we actually create a feedback. In the else, we fetch the data from feedback data from the file where all feedback records are stored.

Once we have this file, we can access the endpoint on http://localhost:3000/api/feedback.

We can now simply use this API directly in our applications React code. See below example.

import { useRef, useState } from 'react';

function HomePage() {

  const [feedbackItems, setFeedbackItems] = useState([]);

  const emailInputRef = useRef();
  const feedbackInputRef = useRef();

  function submitFormHandler(event) {
    event.preventDefault();

    const enteredEmail = emailInputRef.current.value;
    const enteredFeedback = feedbackInputRef.current.value;

    const requestObj = { email: enteredEmail, text: enteredFeedback };

    fetch('/api/feedback', {
      method: 'POST',
      body: JSON.stringify(requestObj),
      headers: {
        'Content-Type': 'application/json'
      }
    }).then(response => response.json())
      .then((data) => {
        console.log(data)
      });
  }

  function loadFeedbackHandler() {
    fetch('/api/feedback')
       .then(response => response.json())
       .then((data) => setFeedbackItems(data.feedback));
  }

  return (
    <div>
      <h1>The Home Page</h1>
      <form onSubmit={submitFormHandler}>
        <div>
          <label htmlFor="email">Your Email Address</label>
          <input type="email" id="email" ref={emailInputRef} />
        </div>
        <div>
          <label htmlFor="feedback">Your feedback</label>
          <textarea rows="5" id="feedback" ref={feedbackInputRef} />
        </div>
        <button>Send</button>
      </form>
      <hr />
      <button onClick={loadFeedbackHandler}>Load Feedback</button>
      <ul>
        {feedbackItems.map(item => <li key={item.id}>{item.text}</li>)}
      </ul>
    </div>
  );
}

export default HomePage;

Basically, apart from the form for handling feedback collection, we have a special button to Load Feedback. When user clicks the button, we call the loadFeedbackHandler function. Within the function body, we make a GET API request to load all feedback items and display them on the screen.

In this case, what we are doing is known as client-side rendering. In other words, the task of fetching the data and showing it is happening on the client or the browser.

2 – NextJS GET API Route with Server-Side Pre-Rendering

While client-side rendering also works fine, the real power of NextJS comes in the case of pre-rendering or server-side rendering.

To demonstrate the same, we create another file named feedback.js within the pages folder. This will contain a normal React component as below.

import { buildFeedbackPath, extractFeedbackData } from "./api/feedback";

function FeedbackPage(props) {
    return <ul>
        {props.feedbackItems.map(item =>
            <li key={item.id}>{item.text}</li>)}
    </ul>

}

export async function getStaticProps() {
    const filePath = buildFeedbackPath();
    const data = extractFeedbackData(filePath);

    return {
        props: {
            feedbackItems: data
        }
    }
}

export default FeedbackPage;

Note that here we have a special function getStaticProps(). The NextJS getStaticProps function is called at the time of building the application. This allows us to pre-render the page on the server itself.

Since our API endpoint is within the same application, we can directly use the necessary functions without using the fetch API. This approach is more efficient. Once we fetch the data, we add the feedback items to the props. These props are then available to the FeedbackPage component.

Once we build and start the application, we can access the feedback page on http://localhost:3000/feedback.

Conclusion

With this, we have successfully learnt how to use NextJS GET API routes for performing server-side pre-rendering of data. This is quite useful for making our web applications faster and efficient.

If you have any comments or queries about this post, please feel free to mention them in the comments section below.

Categories: NextJS

0 Comments

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *