Using forms in Next.js involves leveraging React’s capabilities for managing state and handling form submissions. Next.js, being a React framework, allows you to use any form library or method you prefer for handling forms. Here’s a step-by-step guide to managing forms in Next.js, including basic form handling, validation, and submission.
First, let’s create a basic form in a Next.js page component.
Create a new file in the pages
directory, such as contact.js
.
// pages/contact.js
import { useState } from 'react';
const Contact = () => {
const [formData, setFormData] = useState({
name: '',
email: '',
message: ''
});
const handleChange = (e) => {
const { name, value } = e.target;
setFormData({
...formData,
[name]: value
});
};
const handleSubmit = (e) => {
e.preventDefault();
console.log('Form Data:', formData);
};
return (
<div>
<h1>Contact Us</h1>
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="name">Name:</label>
<input
type="text"
id="name"
name="name"
value={formData.name}
onChange={handleChange}
required
/>
</div>
<div>
<label htmlFor="email">Email:</label>
<input
type="email"
id="email"
name="email"
value={formData.email}
onChange={handleChange}
required
/>
</div>
<div>
<label htmlFor="message">Message:</label>
<textarea
id="message"
name="message"
value={formData.message}
onChange={handleChange}
required
></textarea>
</div>
<button type="submit">Submit</button>
</form>
</div>
);
};
export default Contact;
For form validation, you can use any validation library or implement your own logic. A popular choice is react-hook-form
combined with yup
for schema validation.
npm install react-hook-form yup @hookform/resolvers
react-hook-form
and yup
// pages/contact.js
import { useForm } from 'react-hook-form';
import * as yup from 'yup';
import { yupResolver } from '@hookform/resolvers/yup';
const schema = yup.object().shape({
name: yup.string().required('Name is required'),
email: yup.string().email('Invalid email address').required('Email is required'),
message: yup.string().required('Message is required')
});
const Contact = () => {
const { register, handleSubmit, formState: { errors } } = useForm({
resolver: yupResolver(schema)
});
const onSubmit = data => {
console.log('Form Data:', data);
};
return (
<div>
<h1>Contact Us</h1>
<form onSubmit={handleSubmit(onSubmit)}>
<div>
<label htmlFor="name">Name:</label>
<input
id="name"
{...register('name')}
/>
{errors.name && <p>{errors.name.message}</p>}
</div>
<div>
<label htmlFor="email">Email:</label>
<input
id="email"
{...register('email')}
/>
{errors.email && <p>{errors.email.message}</p>}
</div>
<div>
<label htmlFor="message">Message:</label>
<textarea
id="message"
{...register('message')}
></textarea>
{errors.message && <p>{errors.message.message}</p>}
</div>
<button type="submit">Submit</button>
</form>
</div>
);
};
export default Contact;
For submitting forms, you can use Next.js API routes to handle the form data on the server-side.
Create a new file in the pages/api
directory, such as contact.js
.
// pages/api/contact.js
export default function handler(req, res) {
if (req.method === 'POST') {
const { name, email, message } = req.body;
// Handle form submission, e.g., save to database, send an email, etc.
console.log('Received:', { name, email, message });
res.status(200).json({ message: 'Form submitted successfully' });
} else {
res.status(405).json({ message: 'Method not allowed' });
}
}
// pages/contact.js
import { useForm } from 'react-hook-form';
import * as yup from 'yup';
import { yupResolver } from '@hookform/resolvers/yup';
const schema = yup.object().shape({
name: yup.string().required('Name is required'),
email: yup.string().email('Invalid email address').required('Email is required'),
message: yup.string().required('Message is required')
});
const Contact = () => {
const { register, handleSubmit, formState: { errors } } = useForm({
resolver: yupResolver(schema)
});
const onSubmit = async data => {
const response = await fetch('/api/contact', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
const result = await response.json();
console.log(result);
};
return (
<div>
<h1>Contact Us</h1>
<form onSubmit={handleSubmit(onSubmit)}>
<div>
<label htmlFor="name">Name:</label>
<input
id="name"
{...register('name')}
/>
{errors.name && <p>{errors.name.message}</p>}
</div>
<div>
<label htmlFor="email">Email:</label>
<input
id="email"
{...register('email')}
/>
{errors.email && <p>{errors.email.message}</p>}
</div>
<div>
<label htmlFor="message">Message:</label>
<textarea
id="message"
{...register('message')}
></textarea>
{errors.message && <p>{errors.message.message}</p>}
</div>
<button type="submit">Submit</button>
</form>
</div>
);
};
export default Contact;
Handling forms in Next.js is straightforward with React’s state management and event handling capabilities. You can use form libraries like react-hook-form
for easy form handling and validation, and leverage Next.js API routes for server-side form processing. This approach ensures a smooth and efficient form management workflow in your Next.js applications.