Search code examples
next.jsvercelnext.js13supabase

What is the right way to do a PUT in NextJS 13.4 API? (Response, NextAPIResponse, NextResponse) using the new App Router


What is the right way to do a simple PUT in NextJS 13.4 in the new App Router?

The previous way of doing delete with using NextAPIRequest, NextAPIResponse, using if (req.method === 'PUT') , pulling parameters from the URL via something like this const { id } = request.query;, and throwing error messages with NextAPIResponse seems to be outdated.


Solution

  • Here is an updated PUT api in NextJS 13.4 using the new app routing with error messages included.

    For clarity of the example, I'll include a call to a supabase client; the API you're calling can be different but you can see the error messages and such.

    // FILE NAME /app/api/tacos/route.js
    import { NextResponse } from 'next/server';
    import supabase from '../../supabase/client';
    
    export async function PUT(request) {
        try {
           // ! OLD WAY
           // const { id, newData } = req.body; // ! OLD WAY
           // const dataOldWay = JSON.parse(request.body); // ! OLD WAY
           const { id, newData } = await request.json();
    
           const { data: insertedData, error } = await supabase.from("my_table").update(newData).eq("id", id).select();
    
           if (error) {
              console.log("error catch");
              
              return NextResponse.json({ error: "Internal Server Error" }, { status: 500 });
              // ! THE FOLLOWING DOES NOT WORK - will assume and return a status 200 response
              // return NextResponse.json({ error: 'Internal Server Error', status: 500 });
           }
    
           return NextResponse.json({ insertedData });
        } catch {
            return NextResponse.json({ error: 'Catch Error - Internal Server Error' }, { status: 500 });
        }
    }
    

    For clarity, in Typescript this function signature would be export async function PUT(request: NextRequest) {

    Read more on route handlers here.

    And for completeness, here is a very simple function I used in my client-side app to call this API.

    // This is being called from a Page in your React app
    // 'use client';
    // import React from 'react`;
    // ... define your other import statements here
    
    const putData = async () => {
       const id = "23423dfe-2343-2323223-232323-232323223";
       const data = { key1: "value1", key2: 22222222 };
    
       try {
          const response = await fetch("/api/saveCalculation", {
             method: "PUT",
             body: JSON.stringify({id, data}),
             headers: {
                "Content-Type": "application/json",
             },
          });
    
          if (response.ok) {
              console.log("OKAY");
              const data = await response.json();
              console.log("putData - data updated", responseData);
          } else {
             // Handle the error
             console.log("NOT OKAY");
             const data = await response.json();
             console.log("putData - data NOT updated", responseData);
          }
       } catch (error) {
          console.error("Error", error);
          const data = await response.json();
          console.log("putData - try/catch - error", responseData);
       }
    };
    

    Note: You can of course consolidate responseData declaration higher up in code, but I kept it simple, with a smaller scope for readability.