Breaking Changes
- Conform does automatic type coercion with Zod now. The stripEmptyValue option is removed as empty values are always stripped. (#227, #230, #236, #244)
import { z } from 'zod';
// Before: Use .min(1) to mark a field as required
const required = z.string().min(1, 'Field is required');
// Now: It's required by default and use .optional() to mark it as optional
const required = z.string({ required_error: 'Field is required' });
const optional = z.string().optional();
// Before: Manualy transform the value to the desired type
const numberInput = z.string().transform((val) => Number(value));
// or use preprocess
const checkbox = z.preprocess(value => value === 'on', z.boolean());;
// Now: Conform does type coercion for you
const numberInput = z.number();
// Including checkbox. (Note: boolean coercion only works with default value 'on')
const checkbox = z.boolean().optional();
// You can continue transform / preprocess yourself
// e.g. checkbox with custom value "yes"
const checkbox = z.string().transform(value => value === 'yes');
- The acceptMultipleErrors option is removed since Conform handles multiple errors by default. There is no impact on the validation behaviour. If you were using this option, you can safely remove it. (#228)
const submission = parse(formData, {
// This option can now be removed
acceptMultipleErrors() {
// ...
}
});
- Conform now enforce an array for all errors. If you were setting errors manually, like parsing form data with custom resolver or setting additional errors to the submission object, you need to wrap it in an array. (#228)
export async function action({ request }) {
const formData = await request.formData();
const submission = parse(formData, {
// ...
});
if (submission.intent === 'submit' || !submission.value) {
return json(submission);
}
if (/* some additional checks */) {
return json({
...submission,
error: {
// Pass an array instead of a string
'': ['Something went wrong']
}
})
}
}
- The default value of
useFieldList
is now an empty list instead of an array with one item. (#245)
function Example() {
const [form, fields] = useForm({
// You can set the default value to an array with one item if you want
defaultValue: {
tasks: [''],
},
})
const tasks = useFieldList(fields.tasks);
return (
<form>
<div>
{tasks.map((task, index) => (
<div key={task.key}>
{/* ... */}
</div>
))}
</div>
</form>
);
}
Improvements
- You can now setup a checkbox group using the conform
collection
helper. Check the new guide for details. (#201)
import { conform, useForm } from '@conform-to/react';
import { parse } from '@conform-to/zod';
import { z } from 'zod';
const schema = z.object({
answer: z
.string()
.array()
.nonEmpty('At least one answer is required'),
});
function Example() {
const [form, { answer }] = useForm({
onValidate({ formData }) {
return parse(formData, { schema });
},
});
return (
<form {...form.props}>
<fieldset>
<lengend>Please select the correct answers</legend>
{conform
.collection(answer, {
type: 'checkbox',
options: ['a', 'b', 'c', 'd'],
})
.map((props, index) => (
<div key={index}>
<label>{props.value}</label>
<input {...props} />
</div>
)))}
<div>{answer.error}</div>
</legend>
<button>Submit</button>
</form>
);
}
New Contributors
Full Changelog: v0.7.4...v0.8.0