Overview
Simple application showing how to implement form validation in your Remix application and Yup
I use Yup with React-Hook-From and I was looking to see if I could use it with Remix... I got it working and I thought it would be interesting to share in an video
Remix is a full stack web framework that lets you focus on the user interface and work back through web fundamentals to deliver a fast, slick, and resilient user experience.
The Video
Source Code
import { Form, Link, ActionFunction, redirect, useActionData } from "remix";
import * as Yup from "yup";
import { addProject } from "./dataService";
/**
*
* @param formData
* @returns
*/
const validateForm = async (formData: FormData) => {
const getValidationErrors = (err: any) => {
const validationErrors = {} as any;
err.inner.forEach((error: any) => {
if (error.path) {
validationErrors[error.path] = error.message;
}
});
return validationErrors;
};
// convert form into JSON object
const formJSON: { [key: string]: any } = {};
for (var key of formData.keys()) {
formJSON[key] = formData.get(key);
}
// Yup schema for the object that I am trying to validate
const projectSchema = Yup.object({
name: Yup.string().required("Name is a required field").nullable(),
email: Yup.string()
.email("This is not a valid email")
.required("Email is a required field")
.nullable(),
description: Yup.string()
.required("Description is a required field")
.nullable(),
createdOn: Yup.date().default(() => new Date()),
});
// validate the object and throw error if not valid
try {
const project = await projectSchema.validate(formJSON, { abortEarly: false });
return project;
} catch (error) {
throw getValidationErrors(error);
}
};
/**
*
* @param param0
* @returns
*/
export const action: ActionFunction = async ({ request }) => {
const formData = await request.formData();
try {
// validate
const project = await validateForm(formData);
//save
const newProject = await addProject(project);
return redirect(`/projects/${newProject.id}`);
} catch (errors) {
return { errors };
}
};
export default function NewProject() {
// data returned after submitting the form
const actionData = useActionData();
return (
<div style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.4" }}>
<h2>Remix Form Validation With Yup</h2>
<Form method="post" action="/new-item" noValidate={true}>
<p>
<label>
Name:{" "}
<input
name="name"
type="text"
style={{ borderColor: actionData?.errors["name"] && "red" }}
/>
</label>
<div>{actionData?.errors["name"]}</div>
</p>
<p>
<label>
Email:{" "}
<input
name="email"
type="email"
style={{ borderColor: actionData?.errors["email"] && "red" }}
/>
</label>
<div>{actionData?.errors["email"]}</div>
</p>
<p>
<label>
Description:
<br />
<textarea
name="description"
style={{ borderColor: actionData?.errors["description"] && "red" }}
/>
</label>
<div>{actionData?.errors["description"]}</div>
</p>
<p>
<button type="submit">CREATE</button>
<Link to={"/"} style={{ marginLeft: 12 }}>
<button type="submit">CANCEL</button>
</Link>
</p>
<pre>{JSON.stringify(actionData?.errors, null, 2)}</pre>
</Form>
</div>
);
}
Top comments (1)
Clean and helpful. Thanks!