Mastering Form Architecture: Principles, Best Practices, and Design Patterns in Frontend Development

This article explains how a single Form instance centrally manages form data, uses subscription and notification mechanisms to update components, and demonstrates the Observer and Singleton design patterns with concrete React code examples for building efficient, maintainable frontend forms.

Goodme Frontend Team
Goodme Frontend Team
Goodme Frontend Team
Mastering Form Architecture: Principles, Best Practices, and Design Patterns in Frontend Development

Preface

Form principles and best practices to improve daily development efficiency.

Design patterns used in Form source code to enrich your coding toolbox.

Principles

In a word: At the data layer, a single instance uniformly manages all form data, updates via event subscription and notification, and triggers component re‑render on changes.

Form and Item

Single Instance

Each Form component has an associated instance object that centralizes form state, validation rules, etc. The most common usage is: const [form] = Form.useForm(); This creates a form instance containing a state store and methods for CRUD operations as well as event subscription and notification.

Subscription and Notification

Two simplified code snippets illustrate the core mechanism:

private fieldEntities = [];

// Register Item instance in Form instance
private registerField = (entity) => {
  // Store child instance
  this.fieldEntities.push(entity);
  ...
}

// Notify Items
private notifyObservers = (...args) => {
  ...
  this.getFieldEntities().forEach(({ onStoreChange }) => {
    onStoreChange(...);
  });
  ...
};
class Field extends ... {
  public componentDidMount() {
    ...
    // Item registers itself to the form instance
    this.cancelRegisterFunc = registerField(this);
    ...
  }

  // Callback provided to the form instance for notifications
  public onStoreChange = (prevStore, namePathList, info) => {
    ...
    switch (info.type) {
      case 'reset':
        ...
        break;
      case 'remove':
        ...
        break;
      case 'setField':
        this.reRender();
        ...
        break;
      case 'dependenciesUpdate':
        ...
        break;
      default:
        ...
        break;
    }
    ...
  };

  // Re‑render the Item component
  public reRender() {
    ...
    this.forceUpdate();
  }
}

When the form instance’s state changes, it iterates over Item instances’ onStoreChange methods, causing each Item component to update.

Item components obtain the form instance via React Context and useContext, allowing them to call registerField and register themselves.

Item and Controlled Components

Custom or generic controlled components follow the convention: const { value, onChange, ... } = props; The value is rendered, and changes are sent back via the onChange callback.

value

public getValue = (...) => {
  const { getFieldsValue }: FormInstance = this.props.context;
  const namePath = this.getNamePath();
  ...
};

onChange

// Usage
onChange = (...args) => {
  ...
  dispatch({
    type: 'updateValue',
    namePath,
    value: newValue,
  });
  ...
};

private dispatch = (action) => {
  switch (action.type) {
    case 'updateValue': {
      const { namePath, value } = action;
      this.updateValue(namePath, value);
      break;
    }
    default:
      // Currently we don't have other action. Do nothing.
  }
};

private updateValue = (name, value) => {
  const namePath = getNamePath(name);
  const prevStore = this.store;
  this.updateStore(setValue(this.store, namePath, value));

  this.notifyObservers(prevStore, [namePath], {
    type: 'valueUpdate',
    source: 'internal',
  });
  ...
};

When an Item’s value changes, the form store updates, dependency checks run, observers are notified, and the new value and onChange are injected into child component props, completing the loop.

Design Patterns in Source Code

Observer Pattern

The Observer pattern establishes a one‑to‑many dependency: when an object’s state changes, all dependent objects are notified and automatically updated.

Complex backend editing forms often require inter‑field linkage; using the Form’s built‑in observer architecture simplifies such interactions.

Beyond forms, scenarios like a shopping cart can benefit: multiple components depend on a shared data store, and any change triggers unified notifications to update UI and synchronize with the backend.

Singleton Pattern

function useForm<Values = any>(form?: FormInstance<Values>): [FormInstance<Values>] {
  const formRef = React.useRef<FormInstance>();
  ...
  if (!formRef.current) {
    if (form) {
      formRef.current = form;
    } else {
      ...
      const formStore: FormStore = new FormStore(forceReRender);
      formRef.current = formStore.getForm();
    }
  }
  ...
  return [formRef.current];
}

The useForm hook ensures a single form state instance, preventing conflicts between multiple instances.

Combining Singleton with Observer allows a globally unique data store to be observed by many components, providing a maintainable and decoupled architecture.

Conclusion

In mid‑backend development, forms are indispensable; leveraging their underlying design patterns helps organize code structure effectively.

Understanding the abstracted design patterns beyond the form’s implementation equips you with versatile tools for future projects.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

ReactSingletonObserver PatternForm
Goodme Frontend Team
Written by

Goodme Frontend Team

Regularly sharing the team's insights and expertise in the frontend field

0 followers
Reader feedback

How this landed with the community

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.