🪴 notes

Search

Search IconIcon to open search

react forms

Published May 5, 2023 Last updated May 5, 2023 Edit Source

Setting up forms in react with validation.

packages:

I like to keep things simple. This way of doing things is a bit more complex than I would like. This could be done with html form and zod, but this is more robust I guess.

source

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
...
// main.tsx
const router = createBrowserRouter([
    {
        path: '/',
        element: <App />,
        errorElement: <ErrorPage />,
        children: [
			...,
            {
                path: '/forgotPassword',
                action: forgotPasswordAction,
                element: <ForgotPassword/>
            },
			...
        ]
    },
]);

...

The action prop, is called when the the react-router-dom’s <Form/> component is within the route’s element is submitted with the method='POST' and action='/path'. method='GET' will not trigger the action, but will append form inputs to the url.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
...

// 1.
export async function forgotPasswordAction({ request }: ActionFunctionArgs) {
    const userInput = Object.fromEntries(
        (await request.formData()).entries()
    ) as ForgotPasswordParams;

    try {
		// 4.
        const res = await store.dispatch(authApi.endpoints.forgotPassword.initiate(userInput.email));

        if ('data' in res && res.data.status === 'success') {
            return redirect('/resetPassword/replace_with_reset_token');
        } else {
            alert('fail');
        }

        return null;
    } catch (e) {
        throw new Error((e as Error).message);
    }
}

export default function ForgotPassword() {
	// 2.
    const {
        register,
        handleSubmit,
        formState: { errors }
    } = useForm<ForgotPasswordParams>({
        resolver: zodResolver(LoginParamsSchema.pick({ email: true }))
    });
    const submit = useSubmit();

    const onSubmit: SubmitHandler<ForgotPasswordParams> = (data) => {
		// 3.
        submit(data, {
            method: 'post',
            action: `/forgotPassword`
        })
    }

    return (
		<Form onSubmit={handleSubmit(onSubmit)}>
			<p>
				<span>email</span>
				<input
					{...register("email")}
				/>
				{errors.email?.message}
			</p>
			<p>
				<button type="submit">get reset token</button>
			</p>
		</Form>
    )
}

...

1. the action for the route is defined. 2. We get the methods from react-hook-form’s useForm hook. The resolver is what will do the validation for the form using the zod schema. In this case the schema only have email defined and is picked from LoginParamsSchema. 3. Call submit(data, opts) will trigger the action for the path action points to. The function wrapping submit will only be called when the user form inputs pass handleSubmit’s validation.

4. rtk-q api endpoint called from outside a react component.