npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-jsonschema-form-validation

v0.7.0

Published

Simple form validation using JSON Schema and AJV

Downloads

619

Readme

React JSON Schema Form Validation

npm CI MIT

Validate forms with powerful JSON Schema and Ajv !

This library links JSON Schema, Ajv and Form to :

  • describe data model with JSON Schema
  • validate the form data with Ajv
  • display & customize error messages
  • use your own graphical components to build friendly user forms.

Why RJFV ?

  • Simplicity (no extraneous features, just what you need)
  • Performance (AJV is extremely fast :zap:)
  • Actively maintained
  • The simplest react JSON Schema validation module ever published on npm ! :v:

Other JSON Schema validation modules published on NPM are often complex, with too much features. That's why we created react-jsonschema-form-validation. You'll just need a schema, a form, some fields, and your data. Nothing more. it's S I M P L E

Our philosophy :

  • focused on validation, not UI
  • highly customizable
  • minimal CSS (15 lines) : just a red color to show error message (can be overriden)

Installation

npm install react-jsonschema-form-validation
yarn add react-jsonschema-form-validation

Then import the packaged stylesheet — the minimal CSS mentioned above (a red color for error messages, easily overridden):

import 'react-jsonschema-form-validation/dist/react-jsonschema-form-validation.css';

A minified variant is also shipped: react-jsonschema-form-validation/dist/react-jsonschema-form-validation.min.css.

Getting started

Import modules:

import React, { useState } from 'react';
import { Field, FieldError, Form } from 'react-jsonschema-form-validation';

Define your JSON-Schema:

const demoSchema = {
	type: 'object',
	properties: {
		email: { type: 'string', format: 'email' },
	},
	required: [
		'email',
	],
};

Declare your Form, Field and FieldError components. Pass your schema to the Form props.

Example using a functional component and React hooks:

const DemoForm = (props) => {
	const [formData, setFormData] = useState({ email: '' });
	
	const handleChange = (newData) => {
		// newData is a copy of the object formData with properties (and nested properties)
		// updated using immutability pattern for each change occured in the form.
		setFormData(newData);
	}
	
	const handleSubmit = () => {
		const { doWhateverYouWant } = props;
		doWhateverYouWant(formData); // Do whatever you want with the form data
	}

	return (
		<Form
			data={formData}
			onChange={handleChange}
			onSubmit={handleSubmit}
			schema={demoSchema}
		>
			<label>Email :</label>
			<Field
				name="email"
				value={formData.email}
			/>
			<FieldError name="email" />
			<button type="submit">Submit</button>
		</Form>
	);
}

Same example using a class component:

class DemoForm extends PureComponent {
	state = {
		formData: {
			email: '',
		},
	}
	
	handleChange = (newData) => {
		// newData is a copy of the object formData with properties (and nested properties)
		// updated using immutability pattern for each change occured in the form.
		this.setState({ formData: newData });
	}
	
	handleSubmit = () => {
		const { doWhateverYouWant } = this.props;
		const { formData } = this.state;
		doWhateverYouWant(formData); // Do whatever you want with the form data
	}

	render() {
		<Form
			data={this.state.formData}
			onChange={this.handleChange}
			onSubmit={this.handleSubmit}
			schema={demoSchema}
		>
			<label>Email :</label>
			<Field
				name="email"
				value={formData.email}
			/>
			<FieldError name="email" />
			<button type="submit">Submit</button>
		</Form>
	}
}

🎵 That's all folks !

Custom error messages

Pass an errorMessages map (keyword → function) to <Form> — or to a single <FieldError> — to replace AJV's raw messages. Each function receives the AJV error, which carries the current value of the offending field as error.data, so messages can quote what the user actually typed:

<Form
	data={formData}
	errorMessages={{
		minLength: (e) => `"${e.data}" is too short (min ${e.params.limit} characters)`,
		format: (e) => `"${e.data}" is not a valid ${e.params.format}`,
		required: () => 'This field is required',
	}}
	onChange={handleChange}
	onSubmit={handleSubmit}
	schema={demoSchema}
>
	<Field name="email" value={formData.email} />
	<FieldError name="email" />
	<button type="submit">Submit</button>
</Form>

What error.data contains, per error type:

  • value-level keywords (minLength, format, enum, const, pattern, minimum, … including $data references): the current value of the field;
  • required: the parent object missing the property (AJV reports required on the parent — the missing value itself does not exist). Use e.params.missingProperty for the field name.

Errors also expose error.schema (the failing keyword's value, e.g. 5 for minLength: 5) and error.parentSchema (the enclosing subschema).

Serialization & logging — with verbose, a required error carries the entire parent object in error.data. A JSON.stringify(errors) shipped to monitoring or logs can therefore exfiltrate sensitive sibling fields (a password living next to the missing property, for instance), and cyclic data would make stringify throw. Log a projection of chosen fields (field, keyword, message) rather than raw error objects.

Note — these properties come from AJV's verbose option, enabled on the default instance. If you pass your own instance through the ajv prop of <Form>, set verbose: true yourself to benefit from error.data.

Accessibility

<Field> and <FieldError> wire the essential ARIA attributes for you — no extra props needed:

  • <FieldError> renders with role="alert" by default, so assistive technologies announce the message as soon as it appears. Pass your own role prop to override it.
  • <Field> sets aria-invalid="true" on the rendered element when the field is invalid and revealed (touched, or the form was submitted) — the same condition as the visual error styling, so nothing is announced on a pristine form. It is a plain default: an explicit aria-invalid prop wins.
  • aria-describedby is wired automatically: each <FieldError> registers its id in the parent <Form>, and the matching <Field> references those ids once the field is revealed. The default id is deterministic — jfv<N>-error-<name>, where jfv<N> identifies the <Form> instance so two forms on the same page never collide. A custom id prop on <FieldError> is followed automatically.
  • An aria-describedby you pass to <Field> yourself is merged, not replaced: your ids come first (e.g. a hint text), the error ids after.
  • On a failed submit, keyboard focus moves to the first invalid field (disable with scrollToError={false} on <Form>).
<span id="email-hint">We never share your email.</span>
<Field name="email" aria-describedby="email-hint" value={formData.email} />
<FieldError name="email" />
{/* Once the field is touched (or the form submitted) and invalid,
    the input renders:
    aria-invalid="true" aria-describedby="email-hint jfv1-error-email" */}

The default error id can be computed with the exported helper (formId is available on the form context, see useFormContext):

import { getFieldErrorId } from 'react-jsonschema-form-validation';

getFieldErrorId('jfv1', 'email'); // 'jfv1-error-email'

Known limitations:

  • Rendering several <FieldError> with the same name in one form produces duplicate default ids (invalid HTML). Override id on all but one of them.
  • A name containing spaces cannot be referenced through the generated aria-describedby (it is a space-separated id list). Give such a <FieldError> a custom id.

Reading the form state: useFormContext

Everything <Form> knows is available to its descendants through the useFormContext() hook (a legacy render-prop helper, withFormContext(cb), also exists). Both throw a descriptive error when used outside a <Form>.

import { useFormContext } from 'react-jsonschema-form-validation';

Main context values:

| Name | Description | | --- | --- | | errors | Current validation errors (FormattedError[], each with a normalized field path) | | valid | true when the data matches the schema. Validation is throttled (200 ms by default, throttleDuration prop on <Form>), so valid can lag one beat behind the latest change | | isSubmitted | true once a submit has been attempted (reset after a successful submit, unless resetOnSubmit={false}) | | touchedFields | Names of the fields that have been blurred | | reset() | Resets errors, touchedFields and isSubmitted to their initial state (called automatically after a successful submit unless resetOnSubmit={false}) | | getFieldErrors(names) | Errors for one or several field paths (wildcards like emails.* work) | | isFieldInvalid(names) | true if any of the given fields has an error | | isFieldTouched(names) | true if any of the given fields was touched | | isTouched() | true if at least one field was touched | | touch(names) | Marks fields as touched | | handleFieldChange(event) or handleFieldChange(name, value) | Applies a change programmatically | | formId | Unique id of the <Form> instance (see Accessibility) | | errorMessages | The errorMessages map passed to <Form>, if any |

(The remaining values — fieldErrorsVersion, getFieldErrorDescribedBy, registerFieldError, unregisterFieldError — are internal wiring between <Field> and <FieldError>.)

Disable the submit button while the form is invalid:

const SubmitButton = ({ children }) => {
	const { valid } = useFormContext();
	return (
		<button type="submit" disabled={!valid}>
			{children}
		</button>
	);
};

Show an error summary after a failed submit:

const ErrorSummary = () => {
	const { errors, isSubmitted } = useFormContext();
	if (!isSubmitted || !errors.length) return null;
	return (
		<ul>
			{errors.map((error) => (
				<li key={`${error.field}-${error.keyword}`}>
					{`${error.field}: ${error.message}`}
				</li>
			))}
		</ul>
	);
};

Use them anywhere inside the <Form>:

<Form data={formData} onChange={handleChange} onSubmit={handleSubmit} schema={demoSchema}>
	<ErrorSummary />
	<Field name="email" value={formData.email} />
	<FieldError name="email" />
	<SubmitButton>Submit</SubmitButton>
</Form>

TypeScript

The library is fully typed — .d.ts declarations ship with the package, no @types/... required.

Most relevant exported types:

import type {
    FormProps,         // generic: FormProps<T, C> — T = data shape, C = wrapper element
    FieldProps,        // generic: FieldProps<C> — C = underlying component
    FieldErrorProps,   // generic: FieldErrorProps<C>
    FormContextValue,
    FormattedError,
    ErrorMessageFn,
    ErrorMessagesMap,
} from 'react-jsonschema-form-validation';

Examples

We’ve got many examples, from the most simple to the most advanced.

Live examples are available : here

Documentation

📃 Check out our documentation : here

Changelog

See CHANGELOG.md for release notes.

Licence

MIT

About us

📬 contact : [email protected]

follow us : @53jsdev

github repos : /53js

🚀 website : 53js.fr