Graneet Form LogoGraneet form

Form and Fields

Form, Field, and Rule components reference

Form Components

Graneet Form provides a set of React components for building forms with validation and state management.

Field Component

The Field component registers form fields and handles their state management with optimized re-rendering.

Props

Prop

Type

Render Props

The render function receives these props:

Prop

Type

Render State

The render function also receives state information:

Prop

Type

Example

<Field 
  name="email" 
  render={(props, state) => (
    <div>
      <input 
        type="email"
        value={props.value || ''}
        onChange={(e) => props.onChange(e.target.value)}
        onBlur={props.onBlur}
        onFocus={props.onFocus}
      />
      {state.validationStatus.status === 'invalid' && (
        <span className="error">{state.validationStatus.message}</span>
      )}
    </div>
  )}
>
  <Rule 
    validationFn={(value) => !!value?.includes('@')} 
    message="Please enter a valid email" 
  />
</Field>

Form Component

The Form component provides context to child components and handles form submission.

Usage

import { Form } from 'graneet-form';

<Form form={formInstance}>
  {/* Your form fields */}
</Form>

Example with Submission

function MyForm() {
  const form = useForm<FormData>();
  
  const handleSubmit = form.handleSubmit((data) => {
    console.log('Form data:', data);
  });

  return (
    <form onSubmit={handleSubmit}>
      <Form form={form}>
        <Field name="username" render={...} />
        <Field name="password" render={...} />
        <button type="submit">Submit</button>
      </Form>
    </form>
  );
}

Rule Component

The Rule component adds validation rules to fields. Multiple rules can be added to a single field.

Example

<Field name="password" render={...}>
  <Rule 
    validationFn={(value) => (value?.length || 0) >= 8}
    message="Password must be at least 8 characters"
  />
  <Rule 
    validationFn={(value) => /[A-Z]/.test(value || '')}
    message="Password must contain an uppercase letter"
  />
  <Rule 
    validationFn={(value) => /[0-9]/.test(value || '')}
    message="Password must contain a number"
  />
</Field>

Conditional Validation

<Field name="confirmPassword" render={...}>
  <Rule 
    validationFn={(value, formValues) => value === formValues.password}
    message="Passwords must match"
    when={(formValues) => !!formValues.password}
  />
</Field>

useFormContext Hook

Access the form context within form components:

Prop

Type

Example

function CustomFormField() {
  const { getFormValues, setFormValues } = useFormContext<{
    name: string;
    email: string;
  }>();

  const handleClearForm = () => {
    setFormValues({ name: '', email: '' });
  };

  return (
    <div>
      <button onClick={handleClearForm}>Clear Form</button>
      <pre>{JSON.stringify(getFormValues(), null, 2)}</pre>
    </div>
  );
}

Performance Optimization

  • Field-level subscriptions: Only components watching specific fields re-render
  • Automatic cleanup: Field unregistration happens automatically on unmount
  • Debounced updates: Global form watchers are debounced to prevent spam
  • Minimal re-renders: State changes only trigger necessary component updates