Skip to main content
Version: 3.x

Mutate Data Using Forms

In Front-Commerce, you can handle data mutations using Remix's <Form /> component combined with Front-Commerce's GraphQL mutations. This guide explains how to implement form submissions and handle data mutations effectively.

Using Remix Forms

Remix uses <Form /> component as the primary way to mutate data. When a form is submitted, Remix will:

  1. Call the route's action function
  2. Process the form data
  3. Execute any necessary mutations
  4. Return a response (redirect or data)

Basic Form Structure

Here's a basic example of a password reset form using our theme components:

app/theme/components/PasswordResetForm.tsx
import { Form } from "@remix-run/react";
import Stack from "theme/components/atoms/Layout/Stack";
import Fieldset from "theme/components/atoms/Forms/Fieldset";
import FormItem from "theme/components/molecules/Form/Item";
import { Password } from "theme/components/atoms/Forms/Input";
import FormActions from "theme/components/molecules/Form/FormActions";
import { SubmitButton } from "theme/components/atoms/Button";

export default function PasswordResetForm() {
return (
<Form method="post" action="/reset-password">
<Stack desktopSize="2" mobileSize="4">
<Fieldset>
<Stack size="2">
<FormItem key="password" label="Password">
<Password
name="password"
id="password"
autoComplete="new-password"
required
/>
</FormItem>
<FormItem key="confirmation" label="Confirmation">
<Password
name="password_confirm"
id="password_confirm"
autoComplete="new-password"
required
/>
</FormItem>
</Stack>
</Fieldset>
<FormActions>
<SubmitButton appearance="primary">Change password</SubmitButton>
</FormActions>
</Stack>
</Form>
);
}

Handling Form Submissions

When the form is submitted, Remix calls the route's action function. Here's how to handle the form submission and perform mutations:

app/routes/reset-password.tsx
import { redirect, type ActionFunctionArgs } from "@remix-run/node";
import { json } from "@front-commerce/remix/node";
import { FrontCommerceApp } from "@front-commerce/remix";
import { YourMutationDocument } from "~/graphql/graphql";
import PasswordResetForm from "../theme/components/PasswordResetForm";

export async function action({ request, context }: ActionFunctionArgs) {
const app = new FrontCommerceApp(context.frontCommerce);

const formData = await request.formData();
const userInput = Object.fromEntries(formData.entries());

if (userInput.password !== userInput.password_confirm) {
return json({ errorMessage: "Passwords do not match" }, { status: 400 });
}

try {
// Execute GraphQL mutation
const result = await app.graphql.mutate(YourMutationDocument, {
newPassword: userInput.password,
});

if (result.resetPassword?.success) {
return redirect("/success-page");
} else {
throw new Error("An error occurred", { status: 500 });
}
} catch (e) {
return json({ errorMessage: "An error occurred" }, { status: 500 });
}
}

export default function AccountPasswordResetPage() {
return <PasswordResetForm />;
}
info

In the PasswordResetForm component above, we used the action property to specify which route will handle the form submission. However, when using Remix, if your form is defined in the same route that handles its submission (in this case, reset-password.tsx), you can omit the action property. Remix will automatically submit the form to the current route's action function. For more details, see the Form API documentation.

Key Points

  1. Use Remix's <Form /> component
  2. Access form data using request.formData() in the route's action function
  3. Use app.graphql.mutate() to execute GraphQL mutations
  4. Return appropriate responses (redirect, json data or throw an error)

See also