Skip to main content

React Integration

JSON Forms provides seamless React integration through the @jsonforms/react package, offering both a standalone component and Redux integration options.

Installation

1

Install Core Dependencies

npm install @jsonforms/core @jsonforms/react
2

Install Renderer Set

Choose a renderer set for your UI framework:
npm install @jsonforms/material-renderers

Basic Usage

Standalone Component

The JsonForms component provides a self-contained solution with internal state management:
import { JsonForms } from '@jsonforms/react';
import { materialRenderers, materialCells } from '@jsonforms/material-renderers';
import { useState } from 'react';

function App() {
  const [data, setData] = useState({});
  
  const schema = {
    type: 'object',
    properties: {
      name: { type: 'string' },
      email: { type: 'string', format: 'email' }
    },
    required: ['name', 'email']
  };
  
  const uischema = {
    type: 'VerticalLayout',
    elements: [
      { type: 'Control', scope: '#/properties/name' },
      { type: 'Control', scope: '#/properties/email' }
    ]
  };
  
  return (
    <JsonForms
      schema={schema}
      uischema={uischema}
      data={data}
      renderers={materialRenderers}
      cells={materialCells}
      onChange={({ data, errors }) => setData(data)}
    />
  );
}

JsonForms Component API

The JsonForms component accepts the following props:
interface JsonFormsInitStateProps {
  // Required
  renderers: JsonFormsRendererRegistryEntry[];
  
  // Core properties
  data: any;
  schema?: JsonSchema;
  uischema?: UISchemaElement;
  
  // Optional configuration
  cells?: JsonFormsCellRendererRegistryEntry[];
  config?: any;
  readonly?: boolean;
  validationMode?: 'ValidateAndShow' | 'ValidateAndHide' | 'NoValidation';
  ajv?: Ajv;
  uischemas?: JsonFormsUISchemaRegistryEntry[];
  i18n?: JsonFormsI18nState;
  additionalErrors?: ErrorObject[];
  middleware?: Middleware;
}

interface JsonFormsReactProps {
  onChange?(state: { data: any; errors: ErrorObject[] }): void;
  middleware?: Middleware;
}
If schema is not provided, JSON Forms will automatically generate one from the data. Similarly, if uischema is not provided, a default UI schema will be generated.

React Hooks

JSON Forms provides a comprehensive set of React hooks for building custom renderers and accessing the JSON Forms context.

useJsonForms Hook

Access the complete JSON Forms state and dispatch:
import { useJsonForms } from '@jsonforms/react';

function CustomComponent() {
  const { core, renderers, cells, config, dispatch } = useJsonForms();
  
  // Access current data
  const currentData = core.data;
  
  // Dispatch changes
  const handleUpdate = () => {
    dispatch(Actions.update('path.to.field', newValue));
  };
  
  return <div>{/* Your component */}</div>;
}

Context State Structure

interface JsonFormsStateContext extends JsonFormsSubStates {
  core: JsonFormsCore;           // Data, schema, uischema, errors
  renderers: JsonFormsRendererRegistryEntry[];
  cells?: JsonFormsCellRendererRegistryEntry[];
  config?: any;
  uischemas?: JsonFormsUISchemaRegistryEntry[];
  readonly?: boolean;
  i18n?: JsonFormsI18nState;
  dispatch?: Dispatch<CoreActions>;
}

Higher-Order Components

For class components or advanced use cases, JSON Forms provides HOCs to connect components to the JSON Forms state:

Control HOCs

import { withJsonFormsControlProps } from '@jsonforms/react';
import type { ControlProps } from '@jsonforms/react';

function MyControl({ data, handleChange, path, errors }: ControlProps) {
  return (
    <input
      value={data || ''}
      onChange={(e) => handleChange(path, e.target.value)}
    />
  );
}

export default withJsonFormsControlProps(MyControl);

Available HOCs

  • withJsonFormsControlProps - Standard controls
  • withJsonFormsEnumProps - Enum/select controls
  • withJsonFormsOneOfEnumProps - OneOf enum controls
  • withJsonFormsMultiEnumProps - Multi-select controls
  • withJsonFormsArrayControlProps - Array controls

Redux Integration

For applications already using Redux, JSON Forms provides Redux integration through the @jsonforms/react package.
1

Setup Redux Store

Add the JSON Forms reducer to your Redux store:
import { combineReducers, createStore } from 'redux';
import { jsonformsReducer } from '@jsonforms/react';

const rootReducer = combineReducers({
  jsonforms: jsonformsReducer()
});

const store = createStore(rootReducer);
2

Initialize JSON Forms State

Dispatch initialization actions:
import { Actions } from '@jsonforms/core';

store.dispatch(
  Actions.init(data, schema, uischema, {
    ajv: ajvInstance,
    validationMode: 'ValidateAndShow'
  })
);

// Register renderers
store.dispatch(Actions.registerRenderers(materialRenderers));
3

Use JsonFormsReduxContext

Wrap your app with the Redux context provider:
import { Provider } from 'react-redux';
import { JsonFormsReduxContext } from '@jsonforms/react';

function App() {
  return (
    <Provider store={store}>
      <JsonFormsReduxContext>
        <div>{/* Your components */}</div>
      </JsonFormsReduxContext>
    </Provider>
  );
}

Redux State Structure

The jsonformsReducer() manages the following state:
interface JsonFormsSubStates {
  core: JsonFormsCore;           // Data, schema, uischema, validation
  renderers: JsonFormsRendererRegistryEntry[];
  cells: JsonFormsCellRendererRegistryEntry[];
  config: any;
  uischemas: JsonFormsUISchemaRegistryEntry[];
  i18n: JsonFormsI18nState;
  readonly?: boolean;
}

Custom Redux Reducers

You can add additional reducers alongside JSON Forms:
import { jsonformsReducer } from '@jsonforms/react';

const customReducer = jsonformsReducer({
  myCustomState: myCustomReducer,
  anotherState: anotherReducer
});

const store = createStore(combineReducers({ jsonforms: customReducer }));

Advanced Features

Middleware

Intercept and modify actions before they update the state:
import type { Middleware } from '@jsonforms/core';

const loggingMiddleware: Middleware = (state, action, reducer) => {
  console.log('Before:', state);
  const newState = reducer(state, action);
  console.log('After:', newState);
  return newState;
};

<JsonForms
  {...props}
  middleware={loggingMiddleware}
/>

Custom Validation

Provide a custom AJV instance for validation:
import Ajv from 'ajv';
import addFormats from 'ajv-formats';

const ajv = new Ajv({
  allErrors: true,
  verbose: true,
  strict: false
});
addFormats(ajv);

// Add custom formats
ajv.addFormat('custom-format', /^[A-Z]{3}$/);

<JsonForms
  {...props}
  ajv={ajv}
/>

Internationalization

Provide translations for labels and error messages:
import type { Translator } from '@jsonforms/core';

const germanTranslator: Translator = (key: string, defaultMessage: string) => {
  const translations = {
    'name': 'Name',
    'email': 'E-Mail-Adresse'
  };
  return translations[key] || defaultMessage;
};

<JsonForms
  {...props}
  i18n={{
    locale: 'de-DE',
    translate: germanTranslator
  }}
/>

Component Lifecycle

The JsonForms component manages its internal state and automatically:
  1. Initializes the core state with provided data, schema, and uischema
  2. Generates missing schema/uischema from data if not provided
  3. Validates data on changes (debounced by 10ms)
  4. Emits onChange events with updated data and errors
  5. Updates when props change (schema, data, uischema, etc.)
The onChange callback is debounced to handle rapid changes efficiently, especially important for scenarios like browser autofill.

TypeScript Support

JSON Forms is written in TypeScript and exports all relevant types:
import type {
  ControlProps,
  LayoutProps,
  ArrayLayoutProps,
  CellProps,
  EnumCellProps,
  JsonFormsInitStateProps,
  JsonFormsReactProps,
  TranslateProps
} from '@jsonforms/react';

Next Steps

Build docs developers (and LLMs) love