BuzzForm
BuzzFormDocs

Field Hooks

Complete reference for field hooks — useDataField, useLayoutField, and utilities.

Field Hooks

BuzzForm provides hooks for building custom field components with access to field state, errors, options, and a11y.

Data Field Hook

useDataField

Prop

Type

Aggregates common state for data field components.

Returns:

  • fieldApi - TanStack field API
  • field - Field schema
  • formData - Current form values
  • handleChange / handleBlur - Change handlers
  • label, description, placeholder - Resolved text values
  • isDisabled, isReadOnly, isRequired, isHidden - State flags
  • isInvalid, errors, shouldShowErrors - Error state
  • ariaDescribedBy, descriptionId, errorId - Accessibility IDs

Example:

import { useDataField } from "@buildnbuzz/form-react";
import type { TextField as TextFieldDef } from "@buildnbuzz/form-core";

function CustomTextField() {
  const {
    fieldApi,
    field,
    handleChange,
    handleBlur,
    label,
    placeholder,
    description,
    isDisabled,
    isReadOnly,
    isRequired,
    isInvalid,
    errors,
    ariaDescribedBy,
  } = useDataField<TextFieldDef>();

  const value = (fieldApi.state.value as string) ?? "";

  return (
    <div className="space-y-2">
      {label && (
        <label htmlFor={fieldApi.name}>
          {label}
          {isRequired && <span>*</span>}
        </label>
      )}
      <input
        id={fieldApi.name}
        type="text"
        value={value}
        onChange={(e) => handleChange(e.target.value)}
        onBlur={handleBlur}
        placeholder={placeholder}
        disabled={isDisabled}
        readOnly={isReadOnly}
        aria-invalid={isInvalid}
        aria-describedby={ariaDescribedBy}
      />
      {description && <p className="text-sm">{description}</p>}
      {isInvalid && errors.length > 0 && (
        <p className="text-sm text-red-500">{errors[0]}</p>
      )}
    </div>
  );
}

Layout Field Hook

useLayoutField

Prop

Type

Aggregates state for layout field components.

Returns:

  • field - Field schema
  • form - TanStack form instance
  • label, description - Resolved text values
  • isHidden, isDisabled, isConditionMet - State flags
  • All FieldContextValue properties

Example:

import { useLayoutField } from "@buildnbuzz/form-react";

function CustomGroupField({ children }) {
  const { field, label, isHidden, isDisabled } = useLayoutField();

  if (isHidden) return null;

  return (
    <fieldset disabled={isDisabled}>
      <legend>{label}</legend>
      {children}
    </fieldset>
  );
}

Options Hook

useFieldOptions

Prop

Type

Resolve and normalize options for select, radio, checkbox group.

Returns:

  • options - Normalized options array ({ label, value, disabled, ui }[])
  • isLoading - Always false (reserved for future async sources)

Example:

import { useDataField, useFieldOptions } from "@buildnbuzz/form-react";
import type { SelectField as SelectFieldDef } from "@buildnbuzz/form-core";

function CustomSelectField() {
  const { fieldApi, handleChange, field } = useDataField<SelectFieldDef>();
  const { options } = useFieldOptions(field.options);

  return (
    <select
      value={fieldApi.state.value ?? ""}
      onChange={(e) => handleChange(e.target.value)}
    >
      {options.map((opt) => (
        <option key={opt.value} value={opt.value} disabled={opt.disabled}>
          {opt.label}
        </option>
      ))}
    </select>
  );
}

Error State Hook

useFieldErrorState

Access field errors and validation state.

Returns:

  • errors - Array of error messages
  • isInvalid - Whether field has errors
  • shouldShowErrors - Whether errors should be displayed

A11y IDs Hook

useFieldA11yIds

Generate accessible IDs for form fields.

Returns:

  • descriptionId - ID for description element
  • errorId - ID for error element
  • ariaDescribedBy - Combined value for aria-describedby

Context Hooks

useFieldContext

Read the field context directly:

import { useFieldContext } from "@buildnbuzz/form-react";

function CustomComponent() {
  const { field, form, fieldPath, formData, isHidden } = useFieldContext();

  // Access raw context values
}

useDataFieldContext

Read data field context with guaranteed fieldApi:

import { useDataFieldContext } from "@buildnbuzz/form-react";

function CustomDataField() {
  const { fieldApi, field, fieldPath } = useDataFieldContext();

  // fieldApi is guaranteed to exist
}

useFormContext

Access the form instance from anywhere in the tree:

import { useFormContext } from "@buildnbuzz/form-react";

function SubmitButton() {
  const form = useFormContext();

  return (
    <button
      type="submit"
      disabled={!form.state.canSubmit}
    >
      Submit
    </button>
  );
}

useFieldApi

Convenience hook for just the field API:

import { useFieldApi } from "@buildnbuzz/form-react";

function CustomInput() {
  const fieldApi = useFieldApi();

  return <input ref={fieldApi?.ref} />;
}

Utility Hooks

useNestedErrorCount

Count errors in nested fields (for groups, arrays, tabs):

import { useLayoutField, useNestedErrorCount } from "@buildnbuzz/form-react";

function CustomGroupField({ children }) {
  const { field } = useLayoutField();
  const errorCount = useNestedErrorCount(field.fields);

  return (
    <div className="border p-4 rounded">
      <div className="flex items-center gap-2 mb-4">
        <h3>{field.label}</h3>
        {errorCount > 0 && (
          <span className="bg-red-500 text-white text-xs px-2 py-1 rounded">
            {errorCount} errors
          </span>
        )}
      </div>
      {children}
    </div>
  );
}

useResolvedFieldText

Resolve dynamic strings for label, description, placeholder:

import { useDataField, useResolvedFieldText } from "@buildnbuzz/form-react";

function CustomField() {
  const { field } = useDataField();
  const { label, description, placeholder } = useResolvedFieldText({
    label: field.label,
    description: field.description,
    placeholder: field.placeholder,
  });

  return (
    <>
      <label>{label}</label>
      <input placeholder={placeholder} />
      {description && <p>{description}</p>}
    </>
  );
}

Hook Usage Summary

HookUse Case
useDataFieldCustom data field components
useLayoutFieldCustom layout container components
useFieldOptionsSelect, radio, checkbox group with options
useFieldErrorStateAccess errors and validation state
useFieldA11yIdsGenerate accessible IDs
useFieldContextRaw field context access
useDataFieldContextData field context with guaranteed fieldApi
useFormContextAccess form instance
useFieldApiJust the field API
useNestedErrorCountCount errors in nested fields
useResolvedFieldTextResolve dynamic strings

Out-of-Context Errors

Using hooks outside their required context throws:

useFieldContext must be used within a BuzzForm <Field> or <LayoutField> component
useDataFieldContext must be used within a BuzzForm data field

Wrap your component with <Field> or <LayoutField> first.

On this page