# Reform Error Handling

Reform provides a comprehensive error handling system that helps you manage, format, and display form errors effectively. This document covers the error handling capabilities of Reform.

## Table of Contents

- [Overview](#overview)
- [Error Formatting](#error-formatting)
- [Error Boundaries](#error-boundaries)
- [Custom Error Renderers](#custom-error-renderers)
- [Error Transformation](#error-transformation)
- [API Reference](#api-reference)

## Overview

Reform's error handling system consists of several components:

1. **Error Formatting**: Customize how error messages are displayed
2. **Error Boundaries**: Catch and handle errors in form components
3. **Custom Error Renderers**: Create field-specific error displays
4. **Error Transformation**: Transform error messages before display

## Error Formatting

The `useErrorFormatter` hook provides utilities for formatting error messages with consistent styling and content.

### Basic Usage

```tsx
import { useReform, useErrorFormatter } from '@reform/core';

const MyForm = () => {
  const form = useReform<UserForm>(config);
  const errorFormatter = useErrorFormatter(form, {
    format: 'html',
    includeLabels: true,
  });

  // Format a field error
  const formattedError = errorFormatter.formatFieldError(
    'email',
    'Invalid email format',
    0 // group index
  );

  return (
    <div>
      {/* Display the formatted error */}
      <div dangerouslySetInnerHTML={{ __html: formattedError.content }} />
    </div>
  );
};
```

### Configuration Options

The error formatter can be configured with the following options:

| Option           | Type                         | Default   | Description                                     |
| ---------------- | ---------------------------- | --------- | ----------------------------------------------- |
| format           | `'plain' \| 'html' \| 'jsx'` | `'plain'` | Format of error messages                        |
| includeLabels    | `boolean`                    | `true`    | Include field labels in error messages          |
| includeRuleNames | `boolean`                    | `false`   | Include validation rule names in error messages |

## Error Boundaries

Reform provides error boundary components to catch and handle errors in form components.

### FormErrorBoundary Component

The `FormErrorBoundary` component catches errors in its children and displays a fallback UI.

```tsx
import { useReform, FormErrorBoundary, RecoveryStrategy } from '@reform/core';

const MyForm = () => {
  const form = useReform<UserForm>(config);
  const groups = form.getGroups();

  return (
    <FormErrorBoundary
      formGroups={groups}
      onError={(error, errorInfo) => console.error(error)}
      defaultRecoveryStrategy={RecoveryStrategy.RESET_FORM}
      FallbackComponent={({ errorInfo, resetErrorBoundary, recover }) => (
        <div>
          <h2>Something went wrong!</h2>
          <pre>{errorInfo.error.message}</pre>
          <button onClick={() => recover(RecoveryStrategy.RESET_FORM)}>
            Reset Form
          </button>
        </div>
      )}
    >
      {/* Form components */}
    </FormErrorBoundary>
  );
};
```

### useFormErrorBoundary Hook

For a more convenient API, you can use the `useFormErrorBoundary` hook:

```tsx
import { useReform, useFormErrorBoundary } from '@reform/core';

const MyForm = () => {
  const form = useReform<UserForm>(config);
  const groups = form.getGroups();

  const ErrorBoundary = useFormErrorBoundary(groups, {
    onError: error => console.error(error),
    FallbackComponent: MyCustomErrorComponent,
  });

  return <ErrorBoundary>{/* Form components */}</ErrorBoundary>;
};
```

### Recovery Strategies

Reform provides several recovery strategies for error boundaries:

| Strategy          | Description                               |
| ----------------- | ----------------------------------------- |
| `RESET_FORM`      | Reset the form to its initial state       |
| `RETRY_OPERATION` | Retry the operation that caused the error |
| `IGNORE`          | Ignore the error and continue             |
| `CUSTOM`          | Use a custom recovery function            |

## Custom Error Renderers

Reform allows you to register custom error renderers for specific fields using the `useReformErrorRenderer` hook.

```tsx
import { useReform, useReformErrorRenderer } from '@reform/core';
import { useEffect } from 'react';

const MyForm = () => {
  const form = useReform<UserForm>(config);
  const errorRenderer = useReformErrorRenderer(form);

  // Register a custom renderer for email fields
  useEffect(() => {
    const unregister = errorRenderer.registerErrorRenderer({
      field: 'email',
      renderer: ({ error }) => (
        <div className="email-error">
          <span className="icon">⚠️</span>
          <span className="message">{error}</span>
        </div>
      ),
    });

    return unregister;
  }, []);

  return (
    <form>
      <input {...form.register(0, 'email')} />
      {/* Render the field error with the custom renderer */}
      {errorRenderer.renderFieldError(0, 'email')}
    </form>
  );
};
```

## Error Transformation

You can transform error messages before they are displayed using the `registerTransformer` method of the `useErrorFormatter` hook.

```tsx
import { useReform, useErrorFormatter } from '@reform/core';
import { useEffect } from 'react';

const MyForm = () => {
  const form = useReform<UserForm>(config);
  const errorFormatter = useErrorFormatter(form);

  // Register a custom transformer for email fields
  useEffect(() => {
    errorFormatter.registerTransformer('email', {
      transform: (message, fieldPath, context) => {
        // Add a prefix to all email error messages
        return {
          content: `Email Error: ${message}`,
          format: 'html',
          fieldPath,
          meta: {
            ...context.group,
            groupIndex: context.groupIndex,
          },
        };
      },
    });
  }, []);

  return <form>{/* Form fields */}</form>;
};
```

## API Reference

### useErrorFormatter

```typescript
function useErrorFormatter<T extends Record<string, any>>(
  reform: ReformReturn<T>,
  initialConfig?: Partial<ErrorFormatConfig>
): FormErrorFormatter<T>;
```

#### Parameters

| Parameter     | Type                         | Description                        |
| ------------- | ---------------------------- | ---------------------------------- |
| reform        | `ReformReturn<T>`            | Reform hook return value           |
| initialConfig | `Partial<ErrorFormatConfig>` | Initial error format configuration |

#### Returns

Returns a `FormErrorFormatter<T>` object with the following methods:

| Method              | Description                           |
| ------------------- | ------------------------------------- |
| formatFieldError    | Format a field error message          |
| formatGroupError    | Format a group-level error message    |
| formatFormError     | Format a form-level error message     |
| registerTransformer | Register a custom error transformer   |
| updateFormatConfig  | Update the error format configuration |

### FormErrorBoundary

```typescript
class FormErrorBoundary<T extends Record<string, any>> extends React.Component<ErrorBoundaryProps<T>, ErrorBoundaryState<T>>
```

#### Props

| Prop                    | Type                                                 | Description                                           |
| ----------------------- | ---------------------------------------------------- | ----------------------------------------------------- |
| children                | `React.ReactNode`                                    | Children to render                                    |
| FallbackComponent       | `React.ComponentType<ErrorFallbackProps<T>>`         | Component to render when an error occurs              |
| fallbackRender          | `(props: ErrorFallbackProps<T>) => React.ReactNode`  | Render prop alternative to FallbackComponent          |
| fallback                | `React.ReactNode`                                    | Simple fallback UI as a React Element                 |
| onError                 | `(error: Error, errorInfo: React.ErrorInfo) => void` | Called when an error is caught                        |
| onReset                 | `() => void`                                         | Called when the error boundary recovers from an error |
| defaultRecoveryStrategy | `RecoveryStrategy`                                   | Default recovery strategy to apply                    |
| onCustomRecovery        | `(errorInfo: ErrorInfo<T>) => void`                  | Custom recovery handler                               |
| formGroups              | `FormGroup<T>[]`                                     | Form groups to include in the error info              |

### useFormErrorBoundary

```typescript
function useFormErrorBoundary<T extends Record<string, any>>(
  formGroups: FormGroup<T>[],
  options?: Omit<ErrorBoundaryProps<T>, 'children' | 'formGroups'>
): React.FC<{ children: React.ReactNode }>;
```

#### Parameters

| Parameter  | Type                                                      | Description                              |
| ---------- | --------------------------------------------------------- | ---------------------------------------- |
| formGroups | `FormGroup<T>[]`                                          | Form groups to include in the error info |
| options    | `Omit<ErrorBoundaryProps<T>, 'children' \| 'formGroups'>` | Options for the error boundary           |

#### Returns

Returns a React component that wraps its children in an error boundary.

### useReformErrorRenderer

```typescript
function useReformErrorRenderer<T extends Record<string, any>>(
  reform: ReformReturn<T>
): {
  registerErrorRenderer(config: ErrorRendererConfig<T>): () => void;
  renderError(
    field: FieldPath<T>,
    error: string | null,
    groupIndex?: number
  ): React.ReactNode;
  renderFieldError(groupIndex: number, field: FieldPath<T>): React.ReactNode;
  renderGroupErrors(groupIndex: number): React.ReactNode[];
};
```

#### Parameters

| Parameter | Type              | Description              |
| --------- | ----------------- | ------------------------ |
| reform    | `ReformReturn<T>` | Reform hook return value |

#### Returns

Returns an object with methods for registering and using custom error renderers.

### ErrorTransformer

```typescript
interface ErrorTransformer<T> {
  transform(
    message: string,
    fieldPath: FieldPath<T>,
    context: {
      group: FormGroup<T>;
      groupIndex: number;
      labels: Record<string, any>;
      formatConfig: ErrorFormatConfig;
    }
  ): FormattedErrorMessage;
}
```

### FormattedErrorMessage

```typescript
interface FormattedErrorMessage {
  content: string;
  format: 'plain' | 'html' | 'jsx';
  fieldPath?: string;
  fieldLabel?: string;
  meta?: Record<string, any>;
}
```

### RecoveryStrategy

```typescript
enum RecoveryStrategy {
  RESET_FORM = 'reset_form',
  RETRY_OPERATION = 'retry_operation',
  IGNORE = 'ignore',
  CUSTOM = 'custom',
}
```
