Skip to main content
Skip table of contents

VA Forms Library - About the React component hierarchy

Last Updated: April 28, 2025

The VA Forms Library builds a React application of a form and determines which React components to render based on the description of the form in the form configuration file.

About the Form component, fields, and widgets

At the top level, RJSF uses a Formcomponent to take the schema inputs and render a hierarchy of components for each field of the form:

  • Fields generally match the typeattribute in a schemaobject. There are object fields, array fields, number fields, boolean fields, and string fields. Except for arrays and objects, the fields render a label (via FieldTemplate) and a widget. To specify a particular field, set the ui:field property to number, string, object, boolean, or array.

  • A widget is the HTML input element that accepts data from the user. To specify a particular widget, set the ui:widgetproperty to text, email, checkbox, radio, select, and textarea. While there are many widgets provided by RJSF, the defaults are overwritten with these versions.

Example schema: string object

JS
{
  type: 'string'
}

The two Fieldcomponents determine which fields and widgets to render. SchemaFielduses the two schemas the library accepts, schemaand uiSchema, to determine what other Fieldcomponent to render. In the example below, StringField has been chosen because the schema type is string. The StringFieldcomponent renders TextWidget, based on schemaand uiSchema, because the only information provided was that the field is a string (the default widget type).

JS
<SchemaField>
  <StringField>
    <FieldTemplate>
      <TextWidget/>
    </FieldTemplate>
  </StringField>
</SchemaField>

Example schema: string with enum property

JS
{
  type: 'string',
  enum: ['first', 'second', 'third']
}

The hierarchy for this field uses SelectWidgetinstead of TextWidget, because StringFielddetects the enumproperty in the schema.

JS
<SchemaField>
  <StringField>
    <FieldTemplate>
      <SelectWidget/>
    </FieldTemplate>
  </StringField>
</SchemaField>

While in most cases a field component is responsible for rendering a label and a widget, for objectand arrayschema types, the field component renders additional field components for each of the elements they contain.

Example schema: object

This is an objectschema with two string fields.

JS
{
  type: 'object',
  properties: {
    field1: {
      type: 'string'
    },
    field2: {
      type: 'string'
    }
  }
}

The ObjectFieldcomponent renders a SchemaFieldcomponent for each of its properties. Those properties are both stringtypes, so it looks like the first hierarchy, but nested.

JS
<SchemaField>
  <ObjectField>
    <SchemaField>
      <StringField>
        <FieldTemplate>
          <TextWidget/>
        </FieldTemplate>
      </StringField>
    </SchemaField>
    <SchemaField>
      <StringField>
        <FieldTemplate>
          <TextWidget/>
        </FieldTemplate>
      </StringField>
    </SchemaField>
  </ObjectField>
</SchemaField>

Example schema: ArrayField

ArrayFieldrenders a SchemaFieldcomponent for each item in the array. The library only uses the array field where each item is an object type schema.

JS
{
  type: 'array',
  items: {
    type: 'object',
    properties: {
      field1: {
        type: 'string'
      },
      field2: {
        type: 'string'
      }
    }
  }
}

Field component props

In order for each component to know what to render, field components pass a collection of props down through the component hierarchy. Most are passed to widget components.

  • name: The property name of the current field. For example, the object schema above would be named field1.

  • required: Whether or not the field is required (i.e., the property name is in the schema's requiredarray).

  • schema: The schema for the specific field.

  • uiSchema: The ui schema for this field. (More on this in the section About the uiSchema field component below.)

  • errorSchema: An object that contains the list of errors for the current field and any child properties, if the field is an array or object.

  • idSchema: An object that contains the field IDs for the current field and any child properties. The library generates IDs for each field by joining each property name with an underscore.

  • formData: The actual data entered for the field so far.

  • onChange: The function that's called when data changes. (More on this in the section About the onChange field component below.)

  • onBlur: The function that's called when focus is lost on a widget.

About the onChange field component

When a user enters data, each widget calls onChange. Each component in the hierarchy passes an onChangehandler to child fields. When child data changes, the component combines it with the rest of the data and calls the onChangeprop passed to it from its parent.

JS
{
  type: 'object',
  properties: {
    field1: {
      type: 'string'
    }
  }
}

In this example:

  1. The user types 'a'.

  2. The TextWidgetfor field1 calls onChangewith 'a'.

  3. The onChangeproperty came from the parent ObjectFieldcomponent, which puts 'a' in an object as field1({ field1: 'a' }), then calls the onChangeprop it was passed.

  4. When it reaches the top-level Form component, RJSF runs the JSON Schema validation and passes the results through the component hierarchy.

Similar to Redux, all state is kept in the Form component, or the root of the form. All data processing and validation happens in Form, or is triggered by hooks provided by Form. The Forms Library code built on top of this processes the schemas and form data in Redux, triggered by events provided by Form.

About the uiSchema field component

Along with the regular JSON Schema, a UI schema for UI-specific options that don't fit within the JSON Schema standard is also optionally defined for each field. The UI schema is passed to the form config file as an object, uiSchema, for each field. For more information, visit uiSchemaobject.


JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.