Upgrading to v2
Update your dependencies
Update @formiz/core and @formiz/validations packages to 2.x.x
yarn upgrade @formiz/core @formiz/validationsUpdate React react and react-dom (also @type/react and @type/react-dom if your are using Typescript).
yarn upgrade react@latest react-dom@latest
yarn upgrade -D @types/react@latest @types/react-dom@latestUpgrade <Formiz />
π <Formiz> component doesn't accepts form actions definitions anymore. Now the only props that <Formiz /> accepts are connect and autoForm, and connect is required.
Others props has to be past to useForm now.
Upgrade useForm
New usage
useForm has been split into 3 different hooks: useForm, useFormContext and useFormFields.
π useForm is still used for creating a new form like before. However, there is two changes :
- Now contains form actions definitions (like
onSubmitfor example). - The
subscribeproperty is gone, and the hook now only returns the form's state and actions.
β¨ useFormContext is used to access the form's state and actions in a sub component. It will not create a new form so you can't connect it to a <Formiz> component.
β¨ useFormFields is used to access fields states (not only values).
- Use it at top level with the
connectoption (useFormFields({ connect: form })) or in a sub component (without theconnectoption). - Use a selector to get only the values (
useFormFields({ selector: (field) => field.value })). - Get only some fields with the
fieldsoptions (useFormFields({ fields: ['myField']))
const MyForm = () => {
const form = useForm();
console.log({ values: form.values }) // β Doesn't work anymore
const handleSubmit = (values) => {
console.log({ values })
}
// β Formiz doesn't accept form actions anymore
return <Formiz connect={form} onSubmit={handleSubmit}>
<MyChildren />
<MyField name="myField" />
<MyField name="myOtherField" />
</Formiz>;
};
const MyChildren = () => {
const form = useForm({ subscribe: { fields: ['myField'] } }); // β Doesn't get the form anymore
console.log({ form.values }) // β Doesn't work anymore
return <>
{/* your code here */}
</>;
};const MyForm = () => {
const form = useForm({ onSubmit: (values) => { // β
Form values passed in useForm
console.log({ values })
}});
const values = useFormFields({
connect: form,
selector: (field) => field.value, // β
Get only the values
});
console.log({ values }); // β
{ myField: 'my field value', myOtherField: 'my field value' }
return (
<Formiz connect={form}>
<MyChildren />
<MyField name="myField" />
<MyField name="myOtherField" />
</Formiz>
);
};
const MyChildren = () => {
const form = useFormContext(); // β
Works
const values = useFormFields({
fields: ["myField"],
selector: (field) => field.value,
}); // β
Works
console.log({ values }); // β
{ myField: 'my field value' }
return <>{/* your code here */}</>;
};Form actions updates
π setFieldsValues renamed to setValues
- π
keepPristineoption now defaults to false. - β
keepUnmountedwas removed.setValueswill now always behave as ifkeepUnmountedwastrue.
π invalidateFields renamed to setErrors
π getFieldStepName renamed to getStepByFieldName
π nextStep renamed to goToNextStep
π prevStep renamed to goToPreviousStep
Upgrade useField
Validations API changes
π rule renamed to handler
π Validations don't run on falsy values by default anymore
- You don't need to check on every validation that you have a value (
null,undefined,''orfalse) if your field is not required - If you want to check falsy values (like Formiz v1), just pass the
checkFalsyoption totrue. - Now validations are now executed against formatted value.
<MyField
name="myField"
validations={[
{
rule: (value) => !value || value === "something", // π« `!value ||` useless with v2
message: 'Value must be "something"',
},
]}
/>
<MyField
name="myOtherField"
validations={[
{
rule: (value) => value === "something", // π« Will not be trigger on falsy value with v2
message: 'Value is required and must be "something"',
},
]}
/><MyField
name="myField"
validations={[
{
handler: (value) => value === "something", // β
Only triggered if required pass
message: 'Value must be "something"',
},
]}
/>
<MyField
name="myOtherField"
validations={[
{
handler: (value) => value === "something",
message: 'Value is required and must be "something"',
checkFalsy: true, // β
Opt-in to check also falsy value
},
]}
/>Field props renamed
π onChange renamed to onValueChange
π debounce renamed to debounceValidationsAsync
This will only debounce the async validations and not the value anymore. This prevents a lot of weird behaviors that were existing in v1. Now the value is handled by React v18 to optimize renders.
π asyncValidations renamed to validationsAsync
useField params renamed
π validating.start() renamed to externalProcessing.start() and π validating.end() renamed to externalProcessing.end()
Types changes
You can now type the value of useField by passing a type to the FieldProps type. Also the otherProps will now be typed correctly π.
// β
Pass the value type here ------------------------- π
type MyFieldProps<FormattedValue = string> = FieldProps<string, FormattedValue>
const MyField = <FormattedValue = string,>(props: MyFieldProps<FormattedValue>) => {
const { value, setValue, otherProps } = useField(props);
//...
};The formatted value is by default the same that the value, but you can dynamicly override it.
<MyField<boolean>
// ------- π I need to specify that my formatted value
// Because I format my value to another type
// ----------------- π
formatValue={v => !!v}
/>Not implemented yet
stateSubscriptionforuseFormanduseFormContextAt the moment, both
useFormanduseFormContextwill always return the full form's state. ThestateSubscriptionoption will allows to only return parts of the state, in case you need to further optimize renders on heavy forms.