Getting form data in a route handler in Next.js 13 is a straightforward process

I have been experimenting with next js 13 route handler in order to retrieve login form data. I believed that using the formData method should work, but it seems to be returning an empty object. The login page is located at app/login/page.jsx:

export default function Page() {
    return (
        <div>
            <form action="/api" method="post" className="...">
                <input type="text" name="username" id="username" className="..." />
                <input type="password" name="password" id="username" className="..." />
                <input type="submit" id="submit" value="submit" className="..." />
            </form>
        </div>
    )
}

The corresponding endpoint is at app/api/route.js:

import { NextResponse } from 'next/server';

export async function POST(request):
    const data = request.formData();
    return NextResposne.json({ data })

However, upon submitting the form, the response I receive is:

{"data":{}}

Any suggestions on how to rectify this issue? Thank you.

Answer №1

I have successfully tested this code using JavaScript instead of TypeScript.

import { NextResponse } from 'next/server'



export async function POST(request) {
//   return NextResponse.json({ data: "working fine" })
const formData = await request.formData()
const name = formData.get('name')
const email = formData.get('email')
const myfile = formData.get('myfile')
console.log(myfile);
return NextResponse.json({ name, email })

}

Answer №2

Even after thorough research, the resources regarding this topic in the Next.js documentation were found to be lacking and confusing.

Through persistence and experimentation, I eventually figured out the solution:

import { type NextRequest } from 'next/server';
// ...

export async function POST(request: NextRequest) {
  const data = await request.json();
  console.log({ data });
  // ...
}

Important Note: Utilize NextRequest instead of NextApiRequest.

Answer №3

.formData function has a return value of Promise

(function) Body.formData(): Promise<FormData>

Make sure to use await when calling it:

const formData = await fetchData.formData();

Answer №4

Check out this example:

const settings = { mode: 'cors', credentials: 'same-origin'};

async function fetchData(url) {
    const response = await fetch(url, settings);
    return await response.json();
}

Answer №5

If you find yourself in a situation similar to mine where you are using app-router but your API is located in pages/api, I discovered that the most effective method is to send the file as a base64 string. You can then decode it into a Buffer, create a new form-data object, and send it along. Here's how the code for handling the file looks:

import { API_ENDPOINTS } from '@/API/api';
import { ironOptions } from '@/config/iron-config';
import { AuthData } from '@/models/AuthData';
import { getIronSession } from 'iron-session';
import { NextApiRequest, NextApiResponse } from 'next';
import fetch from 'node-fetch';
import FormData from 'form-data';

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  const session = await getIronSession<AuthData>(req, res, ironOptions);
  const body = req.body;
  //

  //Convert Base64 to Buffer
  const buffer = Buffer.from(JSON.parse(body).file, 'base64');
  // Create a new FormData instance
  const formData = new FormData();
  formData.append('file', buffer);

  //
  let url = `${API_ENDPOINTS['upload_media'].url}`;
  let method = API_ENDPOINTS['upload_media'].type;
  var myHeaders = new Headers();
  myHeaders.append('Authorization', `JWT ${session.token}`);
  myHeaders.append('Content-Type', formData.getHeaders()['content-type']);

  // retrieve user data from database then:
  const response = await fetch(url, {
    method: method,
    headers: myHeaders,
    body: formData,
  });

  // if there's an error, return it
  const data = await response.json();
  if (response.status >= 400) return res.status(response.status).json(data);

  return res.status(response.status).json(data);
}

For the client-side implementation, here's how you can obtain the base64 string:

 function getBase64(file: File) {
   var fileReader = new FileReader();
   if (file) {
     fileReader.readAsDataURL(file);
   }
   return new Promise<string | null>((resolve, reject) => {
     fileReader.onload = function (event: any) {
       resolve(event?.target?.result);
     };
   });
 }

 const reader = new FileReader();
 reader.onload = (e: any) => {
    setSelectedFile(e.target.result);
 };
 reader.readAsDataURL(event.target.files[0]);
 let result: string | null = await getBase64(event.target.files[0]);

Answer №6

One must create a fresh object from the Response and ensure it is converted to a string if it isn't already.

import { NextApiRequest, NextApiResponse } from "next";

export async function POST(req: NextApiRequest, res: NextApiResponse) {
const data = await request.formData();
return new Response(JSON.stringify(data))

}

Please refrain from utilizing ninja code as it is not considered good practice in coding.

In addition, it is advisable to incorporate an extra security measure when handling form data to mitigate potential risks associated with unanalyzed input data.

Answer №7

be patient for it, in this manner:

const information = await request.getData();

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Next.js Project Encountering AWS Amplify Authentication Error: "UserPool not configured"

I am currently developing a project using NextJS and integrating AWS Amplify for authentication with Amazon Cognito. However, I am facing an issue where an error message saying "Auth UserPool not configured" pops up when attempting to log in or sign up. I ...

Optimizing the usage of override Button with Box component in Material-UI

Recently, I've been delving into the Box component in material-UI (https://material-ui.com/components/box/#box) and attempting to understand and write code for it. Specifically, I've been experimenting with overriding a Button component using th ...

Tips for implementing two functions to run within the onClick event handler in React

I am looking to simultaneously execute two functions handleClose and saveData within the onClick method. The specific location where I want this execution to happen: <Button variant="contained" onClick={saveData}&g ...

I encountered a problem with the label for the variant "outlined" in textfields while working with mui 5. Take a look at the image to better grasp the issue at hand

The image displays the issue I am encountering I have attempted to remove the theme codes within the theme provider but the problem persists. The component where I am utilizing it is outlined below: import { useState } from "react"; import { ...

Customizing Material-UI styles with type overrides

Is there a way to change the MuiIconButton-root class when using MuiSvgIcon with the fontSizeSmall attribute? import React from 'react' import { createMuiTheme, ThemeProvider } from '@material-ui/core/styles'; const theme = createMuiT ...

Getting environment variables on the client side in Next.js: A step-by-step guide

How can I retrieve an environment variable in my Next.js application and pass the data into datadogRum.init? // _app.tsx import React from "react"; import { useEffect } from "react"; import type { AppProps } from "next/app"; ...

A simple guide on how to easily retrieve the index of a StepConnector in MaterialUI

Currently, I am utilizing a Stepper component and my goal is to style the connectors individually based on their index. The issue of accessing the current step's index within StepConnector was raised in a GitHub thread back in February. A PR was accep ...

Incorporate HTML and React JS dynamically through AJAX response

Is there a way to activate React JS after inserting AJAX response into a page? The page consists of only a div and script tag as shown below; <div data-react-class="example" data-react-props="{}" data-react-cache-id="example-0& ...

Encountering authentication issues with REST API in React

I'm currently working on a project that involves using Laravel 9 for the backend and React for the frontend. Whenever I attempt to make a request, it returns an unauthorized error from the backend. However, when I test this in Postman, it returns a su ...

Is it possible to incorporate a next.js image onto the background design?

I've encountered an issue while attempting to create a fixed background image with a parallax effect using Tailwind CSS and Next.js Image. If you need to see an example of this in action, check out this Template Monster theme. Here's the code s ...

Shattering the barrier

When using the bubble chart, I encountered an issue with adding line breaks in text. No matter what I tried, such as using \n or , it consistently showed me an error. import React from 'react'; import { BubbleChart,key,data } from 're ...

Choosing the state object name dynamically within a React JS component

I have a quick question about updating state in React. How can I change a specific object in a copy of the state that is selected using e.target.name and then set to e.target.value? For example, if I want to change newState.age when e.target.name = age i ...

Any tips on how to export the index file from Firebase after switching from using require statements to import statements?

As I transition from using requires to importing only in my code, I encountered a challenge when adding "type": "module". After resolving several issues, one problem remains. Initially, I had exports.expressApi = functions.https.onReque ...

Using Django's triple-quotation syntax for raw SQL insert queries: When receiving data from an AJAX request, Django may interpret null values as None when

Currently, I am actively involved in a project combining Django with React. Through using DRF, I have implemented an API route to execute SQL queries on my PostgreSQL database. However, encountering obstacles with the current code arrangement. In my setup ...

How can we use withStyles to customize the styling of a selected ListItem in ReactJS and Material UI?

I am seeking assistance in changing the style of a specific ListItem, similar to what is demonstrated in this Codesandbox. In the Codesandbox example, a global CSS stylesheet is utilized, but I prefer to implement the changes using the withStyle techniqu ...

What is the best practice for updating server-side props on a Next.js page following a client-side mutation?

When working with Next.js, what is the recommended approach for updating data on a page using getServerSideProps after a client-side mutation? I know of one method where you can: const handleRefresh = () => { router.replace(router.asPath); }; ...

What is the best way to transform a standard select input into a React select with multiple options?

Is it possible to transform a regular select dropdown into a multiple select dropdown in React, similar to the one shown in this image? I'm currently using the map method for my select options. https://i.stack.imgur.com/vJbJG.jpg Below is the code s ...

What is the process for implementing custom color props with Material-UI v5 in a React TypeScript project?

Looking to enhance the MUI Button component by adding custom color props values? I tried following a guide at , but encountered errors when trying to implement it in a custom component. The custom properties created in createPalette.d.ts did not work as ex ...

The term 'firestore' is not available on the specified type 'typeof import'

I'm facing some trouble setting up this app because the firebase library that has been exported from firebase/app seems to be missing the firestore() method. I have attached an image for reference. Here is my code. Could someone kindly assist me in re ...

If you're using `react-router-dom` v6 and `useNavigate`, you may need to refresh the page

There is a page called /studentprofile where users can view their profile details. When the user clicks the 'edit profile' button, they are taken to /editprofile where they can update their profile using a form. After clicking the 'update&ap ...