Using remix-hook-form with React Router v7 with flat routes. When initializing the form with useRemixForm(), I get the error: "useHref() may be used only in the context of a component".
Flat routes config: routes.ts
import { type RouteConfig } from '@react-router/dev/routes';
import { flatRoutes } from '@react-router/fs-routes';
export default flatRoutes() satisfies RouteConfig;
Component using the useRemixForm():
import { zodResolver } from '@hookform/resolvers/zod';
import React from 'react';
import { type ActionFunctionArgs, data, Form, useActionData } from 'react-router';
import { getValidatedFormData, RemixFormProvider, useRemixForm } from 'remix-hook-form';
import { z } from 'zod';
const loginSchema = z.object({
email: z.string().email('Email is required'),
password: z.string().nonempty('Password is required'),
});
const resolver = zodResolver(loginSchema);
export async function action({ request }: ActionFunctionArgs) {
const {
errors,
data: formData,
receivedValues: defaultValues,
} = await getValidatedFormData<FormData>(request, resolver);
if (errors) return data({ errors, defaultValues });
return data(formData);
}
function LoginPage() {
const actionData = useActionData<typeof action>();
const loginForm = useRemixForm<z.infer<typeof loginSchema>>({
mode: 'onSubmit',
resolver,
submitConfig: {
method: 'POST',
},
});
const {
handleSubmit,
register,
formState: { errors },
} = loginForm;
return (
<RemixFormProvider {...loginForm}>
<Form onSubmit={handleSubmit} method="POST">
<label>
Email:
<input type="email" {...register('email')} />
{errors.email && <p>{errors.email.message}</p>}
</label>
<label>
Password:
<input type="text" {...register('password')} />
{errors.password && <p>{errors.password.message}</p>}
</label>
<button type="submit">Submit</button>
{actionData && <p style={{ color: 'red' }}>Jeej</p>}
</Form>
</RemixFormProvider>
);
}
export default LoginPage;
What I've tried before
Wrapping the app with a BrowserRouter like so: root.tsx
export default function App() {
return (
<BrowserRouter>
<Outlet />
</BrowserRouter>
);
}
Hydrating the Router like so: entry.client.tsx
import { startTransition, StrictMode } from 'react';
import { hydrateRoot } from 'react-dom/client';
import { HydratedRouter } from 'react-router/dom';
startTransition(() => {
hydrateRoot(
document,
<StrictMode>
<HydratedRouter />
</StrictMode>,
);
});