defineIntent
The
defineIntentfunction is part of Conform's future export. These APIs are experimental and may change in minor versions. Learn more
defineIntent lets you define a custom intent that you can register with configureForms or useForm.
import { defineIntent } from '@conform-to/react/future';
const duplicateTask = defineIntent<(name: string) => void>({
// ...
});#Parameters
definition: IntentHandler
An object that describes how the custom intent behaves.
Most custom intents only need parse(...). Add resolve(...) when the intent should change the value that gets validated or saved.
definition.parse(...args)
Use this to read the arguments passed to the intent and turn them into the typed payload consumed by the other handler methods.
In most cases, this is the first method you should implement.
definition.resolve({ value, payload })
Use this when the intent should update the form value, like update or insert intents.
resolve({ value, payload }) {
return setPathValue(
value,
payload.to,
getPathValue(value, payload.from)
);
}definition.apply({ result, payload })
Use this to adjust the submission result. For example, the built-in reset intent uses this to return { reset: true }, while insert uses it to adjust the result based on validation errors.
definition.touch({ name, payload })
Use this when the intent should mark fields as touched. For example, the built-in validate intent marks the specified field as touched by checking whether name === payload, or marks all fields as touched by returning true.
definition.move({ name, status, targetValue, payload })
Use this when the intent moves list items and you want to preserve their state.
If you omit move, Conform falls back to invalidating the affected state under the changed paths.
#Returns
The same intent handler object, with the dispatcher arguments and payload wired into TypeScript.
#Example
For example, this adds intent.copyField(options) that copies the value from one field to another.
1import { getPathValue, setPathValue } from '@conform-to/dom/future';
2import type { FieldName } from '@conform-to/react/future';
3import { configureForms, defineIntent } from '@conform-to/react/future';
4import { AddressField } from './AddressField';
5
6type CopyField = <FieldShape>(options: {
7 from: FieldName<FieldShape>;
8 to: FieldName<FieldShape>;
9}) => void;
10
11const copyField = defineIntent<CopyField>({
12 parse(options) {
13 if (
14 typeof options !== 'object' ||
15 options === null ||
16 typeof options.from !== 'string' ||
17 typeof options.to !== 'string'
18 ) {
19 throw new Error('Invalid copyField arguments');
20 }
21
22 return options;
23 },
24 resolve({ value, payload }) {
25 const source = getPathValue(value, payload.from);
26 const result = setPathValue(value, payload.to, source);
27
28 return result;
29 },
30 touch({ name, payload }) {
31 return name === payload.to;
32 },
33});
34
35const forms = configureForms({
36 intents: {
37 copyField,
38 },
39});
40
41function Example() {
42 const { form, fields, intent } = forms.useForm({
43 defaultValue: {
44 billing: {
45 street: '123 Main St',
46 city: 'Paris',
47 },
48 shipping: {
49 street: '',
50 city: '',
51 },
52 },
53 });
54
55 return (
56 <form {...form.props}>
57 <AddressField name={fields.billing.name} />
58 <AddressField name={fields.shipping.name} />
59 <button
60 type="button"
61 onClick={() =>
62 intent.copyField({
63 from: fields.billing.name,
64 to: fields.shipping.name,
65 })
66 }
67 >
68 Copy billing address to shipping
69 </button>
70 </form>
71 );
72}