Skip to main content

Usage in React

This guide shows you how to use Forms in React web applications, including setup, configuration, and best practices for web development.

React Setup

Basic React Integration

🌐 React Integration

Forms integrates seamlessly with React web applications using the Form component:

import React from 'react';
import { Form, useFormField, useFormContext } from '@mapples/form';

const LoginForm = () => {
const onSubmit = (data) => {
console.log('Form submitted:', data);
};

return (
<Form
initialValues={{ email: '', password: '' }}
onSubmit={onSubmit}
>
<EmailField />
<PasswordField />
<SubmitButton />
</Form>
);
};

const EmailField = () => {
const {
value,
error,
setValue,
touch
} = useFormField('email', '');

return (
<div>
<label htmlFor="email">Email</label>
<input
value={value || ''}
onChange={(e) => setValue(e.target.value)}
onBlur={() => touch('email')}
type="email"
id="email"
placeholder="Enter your email"
/>
{error && (
<span className="error">{error}</span>
)}
</div>
);
};

const PasswordField = () => {
const {
value,
error,
setValue,
touch
} = useFormField('password', '');

return (
<div>
<label htmlFor="password">Password</label>
<input
value={value || ''}
onChange={(e) => setValue(e.target.value)}
onBlur={() => touch('password')}
type="password"
id="password"
placeholder="Enter your password"
/>
{error && (
<span className="error">{error}</span>
)}
</div>
);
};

const SubmitButton = () => {
const { submitForm } = useFormContext();

return (
<button type="submit" onClick={submitForm}>
Login
</button>
);
};

HTML Form Integration

🔗 HTML Forms

Forms works with standard HTML form elements and provides enhanced functionality:

import React from 'react';
import { Form, useFormField } from '@mapples/form';

const ContactForm = () => {
const onSubmit = (data) => {
console.log('Contact form submitted:', data);
};

return (
<Form
initialValues={{
name: '',
email: '',
message: '',
newsletter: false,
}}
onSubmit={onSubmit}
className="contact-form"
>
<NameField />
<EmailField />
<MessageField />
<NewsletterField />
<SubmitButton />
</Form>
);
};

const NameField = () => {
const nameField = useField('name', {
required: 'Name is required',
minLength: {
value: 2,
message: 'Name must be at least 2 characters',
},
});

return (
<div className="form-group">
<label htmlFor="name">Name</label>
<input
{...nameField}
type="text"
id="name"
placeholder="Your name"
/>
{nameField.error && (
<span className="error-message">{nameField.error}</span>
)}
</div>
);
};

const EmailField = () => {
const emailField = useField('email', {
required: 'Email is required',
pattern: {
value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
message: 'Invalid email address',
},
});

return (
<div className="form-group">
<label htmlFor="email">Email</label>
<input
{...emailField}
type="email"
id="email"
placeholder="your.email@example.com"
/>
{emailField.error && (
<span className="error-message">{emailField.error}</span>
)}
</div>
);
};

const MessageField = () => {
const messageField = useField('message', {
required: 'Message is required',
minLength: {
value: 10,
message: 'Message must be at least 10 characters',
},
});

return (
<div className="form-group">
<label htmlFor="message">Message</label>
<textarea
{...messageField}
id="message"
rows={5}
placeholder="Your message here..."
/>
{messageField.error && (
<span className="error-message">{messageField.error}</span>
)}
</div>
);
};

const NewsletterField = () => {
const newsletterField = useField('newsletter');

return (
<div className="form-group">
<label>
<input
{...newsletterField}
type="checkbox"
/>
Subscribe to newsletter
</label>
</div>
);
};

Advanced React Patterns

Custom Form Components

🎨 Custom Components

Create reusable form components for consistent styling and behavior:

import React from 'react';
import { useField } from '@mapples/form';

const FormField = ({ name, label, type = 'text', validation, ...props }) => {
const field = useField(name, validation);

return (
<div className="form-field">
<label htmlFor={name} className="form-label">
{label}
</label>
<input
{...field}
{...props}
type={type}
id={name}
className={`form-input ${field.error ? 'error' : ''}`}
/>
{field.error && (
<span className="form-error">{field.error}</span>
)}
</div>
);
};

const RegistrationForm = () => {
const { handleSubmit, formState } = useForm({
defaultValues: {
firstName: '',
lastName: '',
email: '',
password: '',
confirmPassword: '',
},
});

const onSubmit = (data) => {
console.log('Registration data:', data);
};

return (
<form onSubmit={handleSubmit(onSubmit)} className="registration-form">
<FormField
name="firstName"
label="First Name"
validation={{
required: 'First name is required',
minLength: {
value: 2,
message: 'First name must be at least 2 characters',
},
}}
/>

<FormField
name="lastName"
label="Last Name"
validation={{
required: 'Last name is required',
minLength: {
value: 2,
message: 'Last name must be at least 2 characters',
},
}}
/>

<FormField
name="email"
label="Email"
type="email"
validation={{
required: 'Email is required',
pattern: {
value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
message: 'Invalid email address',
},
}}
/>

<FormField
name="password"
label="Password"
type="password"
validation={{
required: 'Password is required',
minLength: {
value: 8,
message: 'Password must be at least 8 characters',
},
pattern: {
value: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/,
message: 'Password must contain uppercase, lowercase, and number',
},
}}
/>

<FormField
name="confirmPassword"
label="Confirm Password"
type="password"
validation={{
required: 'Please confirm your password',
validate: (value, formValues) => {
return value === formValues.password || 'Passwords do not match';
},
}}
/>

<button
type="submit"
disabled={!formState.isValid}
className="submit-button"
>
Register
</button>
</form>
);
};

Form with Dynamic Fields

📝 Dynamic Forms

Create forms with dynamic field arrays for complex data structures:

import React from 'react';
import { useForm, useFieldArray } from '@mapples/form';

const DynamicForm = () => {
const { handleSubmit, formState } = useForm({
defaultValues: {
title: '',
items: [{ name: '', quantity: 1, price: 0 }],
},
});

const { fields, append, remove } = useFieldArray('items');

const onSubmit = (data) => {
console.log('Dynamic form data:', data);
};

const addItem = () => {
append({ name: '', quantity: 1, price: 0 });
};

const removeItem = (index) => {
remove(index);
};

return (
<form onSubmit={handleSubmit(onSubmit)} className="dynamic-form">
<div className="form-group">
<label htmlFor="title">Form Title</label>
<input
{...useField('title', {
required: 'Title is required',
})}
type="text"
id="title"
placeholder="Enter form title"
/>
</div>

<div className="items-section">
<h3>Items</h3>
{fields.map((field, index) => (
<div key={field.id} className="item-row">
<div className="form-group">
<label htmlFor={`items.${index}.name`}>Item Name</label>
<input
{...useField(`items.${index}.name`, {
required: 'Item name is required',
})}
type="text"
id={`items.${index}.name`}
placeholder="Item name"
/>
</div>

<div className="form-group">
<label htmlFor={`items.${index}.quantity`}>Quantity</label>
<input
{...useField(`items.${index}.quantity`, {
required: 'Quantity is required',
min: {
value: 1,
message: 'Quantity must be at least 1',
},
})}
type="number"
id={`items.${index}.quantity`}
min="1"
/>
</div>

<div className="form-group">
<label htmlFor={`items.${index}.price`}>Price</label>
<input
{...useField(`items.${index}.price`, {
required: 'Price is required',
min: {
value: 0,
message: 'Price must be at least 0',
},
})}
type="number"
id={`items.${index}.price`}
min="0"
step="0.01"
/>
</div>

<button
type="button"
onClick={() => removeItem(index)}
className="remove-button"
>
Remove
</button>
</div>
))}

<button
type="button"
onClick={addItem}
className="add-button"
>
Add Item
</button>
</div>

<button
type="submit"
disabled={!formState.isValid}
className="submit-button"
>
Submit Form
</button>
</form>
);
};

React-Specific Features

CSS Integration

🎨 Styling

Forms works seamlessly with CSS frameworks and custom styles:

import React from 'react';
import { useForm, useField } from '@mapples/form';
import './Form.css';

const StyledForm = () => {
const { handleSubmit, formState } = useForm({
defaultValues: {
email: '',
password: '',
},
});

const emailField = useField('email', {
required: 'Email is required',
pattern: {
value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
message: 'Invalid email address',
},
});

const passwordField = useField('password', {
required: 'Password is required',
minLength: {
value: 8,
message: 'Password must be at least 8 characters',
},
});

const onSubmit = (data) => {
console.log('Form submitted:', data);
};

return (
<div className="form-container">
<form onSubmit={handleSubmit(onSubmit)} className="styled-form">
<div className="form-header">
<h2>Login</h2>
</div>

<div className="form-body">
<div className="form-group">
<label htmlFor="email" className="form-label">
Email Address
</label>
<input
{...emailField}
type="email"
id="email"
className={`form-input ${emailField.error ? 'error' : ''}`}
placeholder="Enter your email"
/>
{emailField.error && (
<span className="form-error">{emailField.error}</span>
)}
</div>

<div className="form-group">
<label htmlFor="password" className="form-label">
Password
</label>
<input
{...passwordField}
type="password"
id="password"
className={`form-input ${passwordField.error ? 'error' : ''}`}
placeholder="Enter your password"
/>
{passwordField.error && (
<span className="form-error">{passwordField.error}</span>
)}
</div>
</div>

<div className="form-footer">
<button
type="submit"
disabled={!formState.isValid}
className="submit-button"
>
{formState.isSubmitting ? 'Signing In...' : 'Sign In'}
</button>
</div>
</form>
</div>
);
};

Accessibility Features

♿ Accessibility

Forms provides built-in accessibility features for React web applications:

import React from 'react';
import { useForm, useField } from '@mapples/form';

const AccessibleForm = () => {
const { handleSubmit, formState } = useForm({
defaultValues: {
name: '',
email: '',
message: '',
},
});

const nameField = useField('name', {
required: 'Name is required',
});

const emailField = useField('email', {
required: 'Email is required',
pattern: {
value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
message: 'Invalid email address',
},
});

const messageField = useField('message', {
required: 'Message is required',
});

const onSubmit = (data) => {
console.log('Form submitted:', data);
};

return (
<form onSubmit={handleSubmit(onSubmit)} className="accessible-form">
<fieldset>
<legend>Contact Information</legend>

<div className="form-group">
<label htmlFor="name" className="form-label">
Full Name *
</label>
<input
{...nameField}
type="text"
id="name"
aria-describedby={nameField.error ? 'name-error' : undefined}
aria-invalid={nameField.error ? 'true' : 'false'}
className="form-input"
/>
{nameField.error && (
<span id="name-error" className="form-error" role="alert">
{nameField.error}
</span>
)}
</div>

<div className="form-group">
<label htmlFor="email" className="form-label">
Email Address *
</label>
<input
{...emailField}
type="email"
id="email"
aria-describedby={emailField.error ? 'email-error' : undefined}
aria-invalid={emailField.error ? 'true' : 'false'}
className="form-input"
/>
{emailField.error && (
<span id="email-error" className="form-error" role="alert">
{emailField.error}
</span>
)}
</div>

<div className="form-group">
<label htmlFor="message" className="form-label">
Message *
</label>
<textarea
{...messageField}
id="message"
rows={5}
aria-describedby={messageField.error ? 'message-error' : undefined}
aria-invalid={messageField.error ? 'true' : 'false'}
className="form-input"
/>
{messageField.error && (
<span id="message-error" className="form-error" role="alert">
{messageField.error}
</span>
)}
</div>
</fieldset>

<div className="form-actions">
<button
type="submit"
disabled={!formState.isValid}
className="submit-button"
aria-describedby="submit-help"
>
Send Message
</button>
<span id="submit-help" className="form-help">
{formState.isValid ? 'Form is ready to submit' : 'Please fill in all required fields'}
</span>
</div>
</form>
);
};

Best Practices for React

Performance Optimization

⚡ Performance

Optimize your React forms for better performance:

import React, { memo, useCallback, useMemo } from 'react';
import { useForm, useField } from '@mapples/form';

const OptimizedForm = memo(() => {
const { handleSubmit, formState } = useForm({
defaultValues: {
email: '',
password: '',
},
});

const emailField = useField('email', {
required: 'Email is required',
pattern: {
value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
message: 'Invalid email address',
},
});

const passwordField = useField('password', {
required: 'Password is required',
minLength: {
value: 8,
message: 'Password must be at least 8 characters',
},
});

const onSubmit = useCallback((data) => {
console.log('Form submitted:', data);
}, []);

const isFormValid = useMemo(() => formState.isValid, [formState.isValid]);

return (
<form onSubmit={handleSubmit(onSubmit)}>
<div className="form-group">
<label htmlFor="email">Email</label>
<input
{...emailField}
type="email"
id="email"
/>
{emailField.error && (
<span className="error">{emailField.error}</span>
)}
</div>

<div className="form-group">
<label htmlFor="password">Password</label>
<input
{...passwordField}
type="password"
id="password"
/>
{passwordField.error && (
<span className="error">{passwordField.error}</span>
)}
</div>

<button type="submit" disabled={!isFormValid}>
Submit
</button>
</form>
);
});

TypeScript Integration

🔧 TypeScript

Use TypeScript for better development experience with Forms:

import React from 'react';
import { useForm, useField, FormData, FormErrors } from '@mapples/form';

interface ContactFormData {
name: string;
email: string;
message: string;
newsletter: boolean;
}

interface ContactFormErrors {
name?: string;
email?: string;
message?: string;
newsletter?: string;
}

const TypedForm = () => {
const { handleSubmit, formState } = useForm<ContactFormData, ContactFormErrors>({
defaultValues: {
name: '',
email: '',
message: '',
newsletter: false,
},
});

const nameField = useField<ContactFormData>('name', {
required: 'Name is required',
minLength: {
value: 2,
message: 'Name must be at least 2 characters',
},
});

const emailField = useField<ContactFormData>('email', {
required: 'Email is required',
pattern: {
value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
message: 'Invalid email address',
},
});

const messageField = useField<ContactFormData>('message', {
required: 'Message is required',
minLength: {
value: 10,
message: 'Message must be at least 10 characters',
},
});

const newsletterField = useField<ContactFormData>('newsletter');

const onSubmit = (data: ContactFormData) => {
console.log('Contact form submitted:', data);
};

return (
<form onSubmit={handleSubmit(onSubmit)}>
<div className="form-group">
<label htmlFor="name">Name</label>
<input
{...nameField}
type="text"
id="name"
/>
{nameField.error && (
<span className="error">{nameField.error}</span>
)}
</div>

<div className="form-group">
<label htmlFor="email">Email</label>
<input
{...emailField}
type="email"
id="email"
/>
{emailField.error && (
<span className="error">{emailField.error}</span>
)}
</div>

<div className="form-group">
<label htmlFor="message">Message</label>
<textarea
{...messageField}
id="message"
rows={5}
/>
{messageField.error && (
<span className="error">{messageField.error}</span>
)}
</div>

<div className="form-group">
<label>
<input
{...newsletterField}
type="checkbox"
/>
Subscribe to newsletter
</label>
</div>

<button
type="submit"
disabled={!formState.isValid}
>
Send Message
</button>
</form>
);
};

What's Next?

📦 Installation

Installation and configuration guide for using Forms in your projects.

Get Started →

🔧 Hooks

Learn about all available hooks and how to use them effectively.

Hooks Guide →

📚 API Reference

Complete technical documentation for all Forms functions and components.

Full API →