useUnique
Validating the uniqueness of a field is a common requirement so Ra-core provides the useUnique
hook that returns a validator for this use case.
It will call the dataProvider.getList
method with a filter to check whether a record exists with the current value of the input for the field matching the input source.
import { Form, useUnique } from 'ra-core';import { TextInput } from '../components';
const UserCreateForm = () => { const unique = useUnique(); return ( <Form> <div> <TextInput source="username" validate={unique()} /> </div> </Form> );};
Parameters
Section titled “Parameters”useUnique
accepts an object with the following keys, all optional:
Key | Type | Default | Description |
---|---|---|---|
message | string | ra.validation.unique | A custom message to display when the validation fails |
debounce | number | 1000 | The number of milliseconds to wait for new changes before validating |
filter | object | - | Additional filters to pass to the dataProvider.getList call |
resource | string | current from Context | The resource targeted by the dataProvider.getList call |
message
Section titled “message”A custom message to display when the validation fails. Defaults to Must be unique
(translation key: ra.validation.unique
).
It accepts a translation key. The translate
function will be called with the following parameters:
source
: the input namelabel
: the translated input labelvalue
: the current input value
import { Form, useUnique } from 'ra-core';import { TextInput } from '../components';import polyglotI18nProvider from 'ra-i18n-polyglot';
const i18nProvider = polyglotI18nProvider(() => mergeTranslations(englishMessages, { myapp: { validation: { unique: 'Value %{value} is already used for %{field}', }, }, }));
const UserCreateForm = () => { const unique = useUnique(); return ( <Form> <div> <TextInput source="username" validate={unique({ message: 'myapp.validation.unique' })} /> </div> </Form> );};
debounce
Section titled “debounce”The number of milliseconds to wait for new changes before actually calling the dataProvider.getList
method.
import { Form, useUnique } from 'ra-core';import { TextInput } from '../components';
const UserCreateForm = () => { const unique = useUnique(); return ( <Form> <div> <TextInput source="username" validate={unique({ debounce: 2000 })} /> </div> </Form> );};
resource
Section titled “resource”The resource targeted by the dataProvider.getList
call. Defaults to the resource from the nearest ResourceContext
.
This can be useful for custom pages instead of setting up a ResourceContext
.
import { Form, useUnique } from 'ra-core';import { PasswordInput, TextInput } from '../components';
const UserCreateForm = () => { const unique = useUnique(); return ( <Form> <div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}> <TextInput source="username" validate={unique({ resource: 'users' })} /> <PasswordInput source="password" /> </div> </Form> );};
filter
Section titled “filter”Additional filters to pass to the dataProvider.getList
method. This is useful when the value should be unique across a subset of the resource records, for instance, usernames in an organization:
import { FormDataConsumer, Form, useUnique, ReferenceInputBase } from 'ra-core';import { SelectInput, TextInput } from '../components';
const UserCreateForm = () => { const unique = useUnique(); return ( <Form> <div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}> <ReferenceInputBase source="organization_id" reference="organizations"> <SelectInput source="name" /> </ReferenceInputBase> <FormDataConsumer> {({ formData }) => ( <TextInput source="username" validate={unique({ filter: { organization_id: formData.organization_id, }, })} /> )} </FormDataConsumer> </div> </Form> );};