Next.js
better-form works seamlessly with Next.js, supporting both the App Router and Pages Router.
better-form is a client-side library. In Next.js App Router, you'll need to use the "use client" directive.
Installation
npm install @better_form/coreSetup
App Router
1. Import styles in your root layout:
app/layout.tsx
import '@better_form/core/styles';
import type { Metadata } from 'next';
export const metadata: Metadata = {
title: 'My App',
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}2. Create a client component for your form:
app/components/MyForm.tsx
'use client';
import { WizardProvider, WizardContainer, defaultFieldComponents } from '@better_form/core';
import type { WizardConfig } from '@better_form/core';
const config: WizardConfig = {
id: 'contact-form',
steps: [
{
id: 'contact',
title: 'Contact Information',
fieldGroups: [
{
id: 'personal',
fields: [
{
id: 'name',
name: 'name',
label: 'Full Name',
type: 'text',
validation: { required: true },
},
{
id: 'email',
name: 'email',
label: 'Email Address',
type: 'email',
validation: { required: true },
},
],
},
],
},
],
};
export function MyForm() {
const handleSubmit = async (data: Record<string, unknown>) => {
// Handle form submission
console.log('Form submitted:', data);
};
return (
<WizardProvider
config={config}
fieldComponents={defaultFieldComponents}
onSubmit={handleSubmit}
>
<WizardContainer />
</WizardProvider>
);
}3. Use the component in your page:
app/contact/page.tsx
import { MyForm } from '../components/MyForm';
export default function ContactPage() {
return (
<main>
<h1>Contact Us</h1>
<MyForm />
</main>
);
}Server Actions Integration
You can combine better-form with Next.js Server Actions for form handling:
app/actions.ts
'use server';
export async function submitForm(data: Record<string, unknown>) {
// Server-side form processing
// e.g., save to database, send email, etc.
return { success: true };
}app/components/MyForm.tsx
'use client';
import { WizardProvider, WizardContainer, defaultFieldComponents } from '@better_form/core';
import type { WizardConfig } from '@better_form/core';
import { submitForm } from '../actions';
// ... config ...
export function MyForm() {
const handleSubmit = async (data: Record<string, unknown>) => {
const result = await submitForm(data);
if (result.success) {
// Redirect or show success message
}
};
return (
<WizardProvider
config={config}
fieldComponents={defaultFieldComponents}
onSubmit={handleSubmit}
>
<WizardContainer />
</WizardProvider>
);
}With Plugins
If using plugins like Google Places, import their styles too:
app/layout.tsx
import '@better_form/core/styles';
import '@better_form/plugin-google-places/styles';And configure the plugin in your form:
app/components/AddressForm.tsx
'use client';
import { WizardProvider, WizardContainer, defaultFieldComponents } from '@better_form/core';
import { googlePlacesPlugin } from '@better_form/plugin-google-places';
// Enable the plugin
const fieldComponents = {
...defaultFieldComponents,
...googlePlacesPlugin.components,
};Troubleshooting
Hydration Errors
If you encounter hydration errors, ensure your form component is marked with "use client" directive.
Styles Not Loading
Make sure you're importing styles in the correct file:
- App Router:
app/layout.tsx - Pages Router:
pages/_app.tsx
TypeScript Errors
Ensure your tsconfig.json includes the necessary compiler options:
tsconfig.json
{
"compilerOptions": {
"moduleResolution": "bundler",
"esModuleInterop": true
}
}