I have a form that contains input fields. Once you submit them, I want to immediately display them in the list item without waiting for the API to finish responding. If the API responds with an error, I want to hide them.
However, I also have validation that is triggered on the action, which should be displayed if one of the fields is blank. This is the validation for error fields. I want them to be shown immediately before calling the API. Should I replace them with client-side validation using react-hook-form? How can I fix this? Please check my codesandbox below.
Click here —–> CODESANDBOX
CODE
import { json, type ActionFunctionArgs } from "@remix-run/node";
import { useActionData, useFetchers, useLoaderData } from "@remix-run/react";
import { AddProductForm } from "../components/product-form";
import { ProductItem } from "../components/product-item";
import { productValidate } from "../product-validate";
export async function action({ request }: ActionFunctionArgs) {
const formData = await request.formData();
const { name, size } = Object.fromEntries(formData);
const errors = productValidate({ name: String(name), size: String(size) });
if (errors) {
return json({ ok: false, errors }, 400);
}
return null;
}
export async function loader({ request }: LoaderFunctionArgs) {
const products = [
{
id: Math.random(),
name: "Product A",
size: "Large",
},
];
return { products };
}
export default function UploadProductsRoute() {
let { products } = useLoaderData<typeof loader>();
const actionData = useActionData<typeof action>();
const fetchers = useFetchers();
const optimisticProducts = fetchers.reduce<[]>((memo, f) => {
if (f.formData) {
const data = Object.fromEntries(f.formData);
if (!products.map((e) => e.id).includes(data.id)) {
memo.push(data);
}
}
return memo;
}, []);
products = [...products, ...optimisticProducts];
return (
<div className="container flex flex-col pt-8 mb-32">
<div className="mb-6">
<h1 className="text-xl">Add your products</h1>
</div>
<AddProductForm actionData={actionData} />
<div className="my-6">
<h1 className="text-xl font-semibold">Products you've added</h1>
</div>
<div className="border rounded-lg text-sm">
<div className="divide-y">
{products.map((product) => (
<ProductItem
key={product.id}
name={product.name}
size={product.size}
/>
))}
</div>
</div>
</div>
);
}