View on GitHub

React Hook Form Plus

(RHF+)

Controller children function

Purpose

Currently, the Controller component in React Hook Form (RHF) only supports a render prop for rendering the controlled component. This enhancement adds support for a children function prop.

Benefits

API Changes

Property updates

export type ControllerProps<
  TFieldValues extends FieldValues = FieldValues,
  TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
  TTransformedValues = TFieldValues,
> = (
  | {
      render: ControllerRender<TFieldValues, TName>;
    }
  | {
      children: ControllerRender<TFieldValues, TName>; // New: children prop as alternative
    }
) &
  UseControllerProps<TFieldValues, TName, TTransformedValues>;

// New shared type for the render/children function
export type ControllerRender<
  TFieldValues extends FieldValues,
  TName extends FieldPath<TFieldValues>,
> = ({
  field,
  fieldState,
  formState,
}: {
  field: ControllerRenderProps<TFieldValues, TName>;
  fieldState: ControllerFieldState;
  formState: UseFormStateReturn<TFieldValues>;
}) => React.ReactElement;

Description

The Controller component now supports both render and children function patterns for rendering controlled components. Both props accept identical function signatures and provide the same field, fieldState, and formState arguments to their respective functions.

Behavior

The component internally handles both patterns identically, with the function receiving field control props, field state, and form state as arguments.

Examples

Previous use cases

<Controller
  control={control}
  name="test"
  render={({
    field: { onChange, onBlur, value, ref },
    formState,
    fieldState,
  }) => (
    <>
      <input
        onChange={onChange} // send value to hook form
        onBlur={onBlur} // notify when input is touched
        value={value} // return updated value
        ref={ref} // set ref for focus management
      />
      <p>{formState.isSubmitted ? 'submitted' : ''}</p>
      <p>{fieldState.isTouched ? 'touched' : ''}</p>
    </>
  )}
/>

New supporting usage

<Controller
  control={control}
  name="test"
>
  ({field: {onChange, onBlur, value, ref}, formState, fieldState}) => (
  <>
    <input
      onChange={onChange} // send value to hook form
      onBlur={onBlur} // notify when input is touched
      value={value} // return updated value
      ref={ref} // set ref for focus management
    />
    <p>{formState.isSubmitted ? "submitted" : ""}</p>
    <p>{fieldState.isTouched ? "touched" : ""}</p>
  </>
  )
</Controller>

Limitations

Backward Compatibility

This feature is fully backward compatible. The existing render prop pattern continues to work, and the children function pattern is an additional option.