Frontend Development 19 min read

Understanding rc-form: Internals, APIs, and Usage in React Forms

This article provides a comprehensive overview of rc-form, a React library used by Ant Design to manage form state, validation, and data collection, explaining why it is needed, its core APIs, practical usage examples, and a deep dive into its internal implementation.

政采云技术
政采云技术
政采云技术
Understanding rc-form: Internals, APIs, and Usage in React Forms

rc-form is a lightweight library that Ant Design's Form component relies on to centralize form data management, validation, and value collection in React applications, eliminating the need for repetitive onChange handlers.

Why use rc-form? It creates a single data store (fieldsStore) that handles field registration, value updates, and validation, allowing developers to focus on UI logic while rc-form takes care of the boilerplate.

Main APIs

Api Name

Description

Type

getFieldDecorator

Wraps a field component for two‑way binding

Function(name)

getFieldsValue

Returns values of a set of fields (optionally all)

(nameList?: NamePath[], filterFunc?: (meta) => boolean) => any

getFieldValue

Gets the value of a specific field

(name: NamePath) => any

setFieldsValue

Sets values for multiple fields

(values) => void

setFields

Updates the status of a group of fields

(fields: FieldData[]) => void

validateFields

Triggers validation for specified fields

(nameList?: NamePath[]) => Promise

isFieldValidating

Checks whether a field is currently validating

(name: NamePath) => boolean

getFieldProps

Generates the props that should be spread onto a field component

(name: NamePath) => any

Basic usage example

import React, { Component } from "react";

export default class index extends Component {
  state = { value1: "peter", value2: "123", value3: "23" };

  onChange1 = ({ target: { value } }) => { this.setState({ value1: value }); };
  onChange2 = ({ target: { value } }) => { this.setState({ value2: value }); };
  onChange3 = ({ target: { value } }) => { this.setState({ value3: value }); };

  submit = async () => {
    const { value1, value2, value3 } = this.state;
    const obj = { value1, value2, value3 };
    const res = await axios("url", obj);
  };

  render() {
    const { value1, value2, value3 } = this.state;
    return (
用户名:
密码:
年龄:
提交
);
  }
}

When the form grows, writing dozens of onChange handlers becomes unwieldy; rc-form solves this by providing createForm (a higher‑order component) that injects a form prop with the APIs above.

Using rc-form with Ant Design

import { createForm } from "../../rc-form";

const RcForm = (props) => {
  const { form: { getFieldDecorator, validateFields } } = props;

  const handleSubmit = (e) => {
    e && e.stopPropagation();
    validateFields((err, value) => {
      if (!err) {
        console.log(value);
      }
    });
  };

  return (
姓名:
{getFieldDecorator("username", {
          rules: [{ required: true, message: "请输入用户名!" }],
          initialValue: 'initialValue',
        })(
)}
密码:
{getFieldDecorator("password", {
          rules: [
            { required: true, message: "请输入密码!" },
            { pattern: /^[a-z0-9_-]{6,18}$/, message: '只允许数字!' },
          ],
        })(
)}
提交
);
};

export default createForm()(RcForm);

Internal implementation highlights

getFieldDecorator(name, fieldOption) registers the field, retrieves its meta data from fieldsStore , and returns a function that clones the original component with the generated props and value bindings.

getFieldProps(name, usersFieldOption = {}) {
  const fieldOption = {
    name,
    trigger: DEFAULT_TRIGGER,
    valuePropName: 'value',
    validate: [],
    ...usersFieldOption,
  };
  const { rules, trigger, validateTrigger = trigger, validate } = fieldOption;
  const fieldMeta = this.fieldsStore.getFieldMeta(name);
  if ('initialValue' in fieldOption) {
    fieldMeta.initialValue = fieldOption.initialValue;
  }
  const inputProps = {
    ...this.fieldsStore.getFieldValuePropValue(fieldOption),
    ref: this.getCacheBind(name, `${name}__ref`, this.saveRef),
  };
  // bind validation triggers
  const validateRules = normalizeValidateRules(validate, rules, validateTrigger);
  const validateTriggers = getValidateTriggers(validateRules);
  validateTriggers.forEach(action => {
    if (inputProps[action]) return;
    inputProps[action] = this.getCacheBind(name, action, this.onCollectValidate);
  });
  if (trigger && validateTriggers.indexOf(trigger) === -1) {
    inputProps[trigger] = this.getCacheBind(name, trigger, this.onCollect);
  }
  return inputProps;
}

The fieldsStore object holds two maps: fieldsMeta (static configuration such as rules, triggers, and original props) and fields (dynamic state like value , dirty , errors , validating ). Methods like getFieldMeta , setFields , and validateFieldsInternal manipulate these structures.

onCollectValidate(name_, action, ...args) {
  const { field, fieldMeta } = this.onCollectCommon(name_, action, args);
  const newField = { ...field, dirty: true };
  this.fieldsStore.setFieldsAsDirty();
  this.validateFieldsInternal([newField], { action, options: { firstFields: !!fieldMeta.validateFirst } });
}

When a validation‑triggering event occurs, onCollectValidate marks the field dirty, runs the async validator, and updates the store with any errors. For non‑validation events, onCollect simply updates the value and forces a re‑render.

Overall design

createForm(options) is a thin wrapper around createBaseForm , which returns a higher‑order component. This HOC injects a form prop into the wrapped component, granting access to all rc‑form APIs. The injected form object interacts with fieldsStore to keep the UI in sync with the underlying data model.

Conclusion

rc-form provides a robust solution for managing complex form state and validation in React, but developers should be aware of potential re‑render performance costs; for high‑performance scenarios, the newer rc-field-form library may be a better fit.

JavaScriptreactValidationAnt Designrc-formform
政采云技术
Written by

政采云技术

ZCY Technology Team (Zero), based in Hangzhou, is a growth-oriented team passionate about technology and craftsmanship. With around 500 members, we are building comprehensive engineering, project management, and talent development systems. We are committed to innovation and creating a cloud service ecosystem for government and enterprise procurement. We look forward to your joining us.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.