Skip to content

Latest commit

 

History

History
928 lines (640 loc) · 21.3 KB

CHANGELOG.md

File metadata and controls

928 lines (640 loc) · 21.3 KB

Changelog

[7.6.0] - 2021-05-15

Changed

  • useForm will register missing inputs from defaultValues
const App = () => {
  const { register, handleSubmit } = useForm({
    defaultValues: {
      test: { firstName: 'bill', lastName: 'luo' },
    },
  });

  const onSubmit = (data) => {
    // missing registered input will be included
    console.log(data); // { test: { firstName: 'bill', lastName: 'luo' } }
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register('test.firstName')} />
      <button />
    </form>
  );
};

[7.5.0] - 2021-05-09

Changed

  • isSubmitSuccessful will return false when handleSubmit callback failed with Error or Promise reject.
  • unmounted input will no longer get validated even with shouldUnregister: false

[7.4.0] - 2021-05-04

Added

  • new name prop for useFormState to subscribe to individual inputs.
useFormState({
  name: 'inputName', // optional and can be array of inputs' name as well
});

[7.2.2] - 2021-04-21

Changes

  • set shouldUnregister to true will not shallow merge defaultValues

[7.2.0] - 2021-04-19

Changes

  • shouldUnregister config to remove input value after unmount
// Global config (can't be overwrite)
useForm({
  shouldUnregister: true // default to false
})

// Component/Hook level config (can not overwrites global config)
register('test', {
  shouldUnregister: true // default to false
})

<Controller  shouldUnregister={true} />

useController({ shouldUnregister: true })

useFieldArray({ shouldUnregister: true })

[7.0.6] - 2021-04-12

Changes

  • register will retrieve onChange's target value when component'ref is not a valid input element.

[7.0.0-rc.7] - 2021-03-28

Changes

  • change type name from RefCallbackHandler to UseFormRegisterReturn for register callback's return

[7.0.0-rc.7] - 2021-03-23

Changes

  • useFieldArray will produce an empty array [] when no field is presented.

[7.0.0-rc.1] - 2021-03-08

Changes

  • setValue with field array will register all inputs before rendering.

[7.0.0-beta.17] - 2021-03-03

Changes

  • append, prepend and insert will register deeply nested inputs at useFieldArray.

[7.0.0-beta.15] - 2021-02-27

Changes

  • typescript array index restriction removed.
  • append, prepend and insert will register inputs during each action at useFieldArray.

[7.0.0-beta.11] - 2021-02-20

Changes

  • change ArrayKey type to number | '${number}'

[7.0.0-beta.10] - 2021-02-19

Changes

  • Change useController's meta into fieldState and include formState, these change will be applied to Controller too.
- const { field, meta } = useController({ control });
+ const { field, fieldState, formState } = useController({ control });

[7.0.0-beta.9] - 2021-02-19

Changes

  • typescript array index support is changed to 49 instead of 99

[7.0.0-beta.4] - 2021-02-08

  • Breaking change: valueAs will be run before the built-in validation and resolver
- <input {...register('test', { validate: (data: string) => {}, valueAsNumber: true })} />
+ <input {...register('test', { validate: (data: number) => {}, valueAsNumber: true })} />

[7.0.0-beta.1] - 2021-02-08

Changes

  • useWatch will no longer required defaultValue for field Array

[7.0.0-beta.0] - 2021-02-06

Changes

  • Breaking change: shallow merge defaultValues with result (#4074)
useForm({ defaultValues: { test: 'test' } });

getValues(); // v6 will return {}
getValues(); // v7 will return { test: 'test' }

[v7.0.0-alpha.2] - 2021-02-04

Changes

  • Breaking change: setError's shouldFocus option has been moved into the third argument.
- setError('test', { type: 'type', message: 'issue', shouldFocus: true })
+ setError('test', { type: 'type', message: 'issue' }, { shouldFocus: true })
  • Breaking change: type name changes:
- UseFormMethods
+ UseFormReturn
- UseFormOptions
+ UseFormProps
- UseFieldArrayMethods
+ UseFieldArrayReturn
- UseFieldArrayOptions
+ UseFieldArrayProps
- UseControllerMethods
+ UseControllerReturn
- UseControllerOptions
+ UseControllerProps
- ArrayField
+ FieldArray

Fixes

  • fix setValue with Controller and reset with useFieldArray issues: 4111 & 4108 (#4113)

[v7.0.0-alpha.2] - 2021-02-02

Changes

  • Breaking change: setError's shouldFocus option has been moved to the third argument.
- setError('test', { type: 'type', message: 'issue', shouldFocus: true })
+ setError('test', { type: 'type', message: 'issue' }, { shouldFocus: true })

Fixes

  • fix #4078 issue with watch + mode: onChange

Improvements

  • remove internal deep clone (#4088)
  • remove transformToNestObject (#4089)

[v7.0.0-alpha.1] - 2021-02-01

Changes

  • field name reference will be removed with unregister (#4010)

  • Breaking change: improve field array remove result and no longer remove field array value after unmount

const { remove } = useFieldArray({ name: 'test' })
remove();
getValues(); // V6: result form value {}
getValues(); // V7: result form value { test: [] }

Improvements

  • change internal field names into Set (#4015)
  • improve onChange perf with `resolver (#4017)
  • improve field array name look up perf (#4030)

[v7.0.0-alpha.0] - 2021-01-31

Added

  • new custom hook useFormState (#3740)
const { isDirty, errors } = useFormState();
  • watch support can subscribe to the entire form with a callback
watch((data, { name, type }) => {
  console.log('formValue', data);
  console.log('name', name);
  console.log('type', type);
});
  • useController includes new isValidating state (#3778)
  • useController includes new error state (#3921)
const {
  meta: { error, isValidating },
} = useController({ name: 'test' });
  • new unregister second argument (#3964)
unregister('test', { keepDirty: true });
  • Resolver add field being validated (#3881)
- resolver: (values: any, context?: object) => Promise<ResolverResult> | ResolverResult
+ resolver: (
+    values: any,
+    context?: object,
+    options: {
+       criteriaMode?: 'firstError' | 'all',
+       names?: string[],
+       fields: { [name]: field } // Support nested field
+    }
+  ) => Promise<ResolverResult> | ResolverResult
  • useFieldArray action can focus input by name and index
append(object, config: { shouldDirty: boolean, focusIndex: number, focusName: string })
insert(object, config: { shouldDirty: boolean, focusIndex: number, focusName: string })
prepend(object, config: { shouldDirty: boolean, focusIndex: number, focusName: string })

Changes

  • Breaking change: No longer support IE 11 support

  • Breaking change: register has been changed from register at ref to a function which needs to be spread as props.

- <input ref={register, { required: true }} name="test" />
+ <input {...register('name', { required: true })} />
+ <TextInput {...register('name', { required: true })} />
  • Breaking change: name with array will only support dot syntax instead of brackets.
- test[2].test
+ test.2.test
  • Breaking change: remove as prop at Controller and fix render prop consistency (#3732)
- <Controller render={props => <input {...props} />} />
+ <Controller render={({ field }) => <input {...field} />} />
  • Breaking change: remove errors alias (#3737)
- const { errors } = useForm();
+ const { formState: { errors } } = useForm();
  • Breaking change: improved reset second argument (#3905)
- reset({}, { isDirty: true })
+ reset({}, { keepIsDirty: true })
  • Breaking change: change touched to touchedFields for consistency (#3923)
- const { formState: { touched } } = useForm();
+ const { formState: { touchedFields }} = useForm();
  • Breaking change: trigger will no longer return validation result.
- await trigger('test') // return true or false
+ trigger('test') // void
  • remove isSubmitting proxy (#4000)

  • input register will no longer be removed due to unmount, user will have to manually invoke unregister

Improvements

  • useWatch internal mechanism improvement (#3754)
  • Controller and useController apply useFormState internally and improve performance (#3778)
  • register type support for input name (#3738)
  • Controller and useCOntroller type support for input name (#3738)
  • useFieldArray internal logic and data structure improvement (#3858)
  • improve useFieldArray internal fields update with subscription (#3943)
  • improve tests structure (#3916)
  • useWatch type improvement (#3931)
  • improve type support for nested field array with const (#3920)
  • improve useFieldArray internal type structure (#3986)
  • MutationObserver removed from useForm

[6.15.0] - 2021-02-02

Changed

  • radio input default selection will return null instead of empty string ''
  • valueAsNumber with empty input will return NaN instead of 0

[6.14.0] - 2020-12-31

Changed

  • setValue without shouldUnregister:false will no longer deep clone its value instead with shallow clone

Added

  • new formState isValidating, this will set to true during validation.
const {
  formState: { isValidating },
} = useForm();

[6.12.0] - 2020-12-12

Changed

  • When invoking reset({ value }) value will be shallow clone value object which you have supplied instead of deepClone.
// ❌ avoid the following with deep nested default values
const defaultValues = { object: { deepNest: { file: new File() } } };
useForm({ defaultValues });
reset(defaultValues); // share the same reference

// ✅ it's safer with the following, as we only doing shallow clone with defaultValues
useForm({ deepNest: { file: new File() } });
reset({ deepNest: { file: new File() } });

Added

  • New custom hook useController: This custom hook is what powers Controller, and shares the same props and methods as Controller. It's useful to create reusable Controlled input, while Controller is the flexible option to drop into your page or form.
import React from 'react';
import { TextField } from '@material-ui/core';
import { useController } from 'react-hook-form';

function Input({ control, name }) {
  const {
    field: { ref, ...inputProps },
    meta: { invalid, isTouched, isDirty },
  } = useController({
    name,
    control,
    rules: { required: true },
    defaultValue: '',
  });

  return <TextField {...inputProps} inputRef={ref} />;
}

[6.12.0] - 2020-11-28

Changed

  • useWatch will retrieve the latest value from reset(data) instead of return defaultValue
useWatch({
  name: 'test',
  defaultValue: 'data', // this value will only show on the inital render
});
  • TS: name changed from ValidationRules to RegisterOptions due to valueAs functionality included as register function.

Added

  • register function with additional options to transform value

    • valueAsDate
    • valueAsNumber
    • setValue
register({
  valueAsNumber: true,
});

register({
  valueAsNumber: true,
});

register({
  setValueAs: (value) => value,
});

Added

[6.11.0] - 2020-11-07

Changed

  • defaultValues is required to measure isDirty, keep a single source of truth to avoid multiple issues raised around isDirty
  • when watch with useFieldArray, fields object is no longer required as defaultValue
- watch('fieldArray', fields);
+ watch('fieldArray');

[6.10.0] - 2020-10-31

Added

  • Controller will have an extra ref props to improve DX in terms of focus management.
<Controller
  name="test"
  render={(props) => {
    return (
      <input
        value={props.value}
        onChange={props.onChange}
        ref={props.ref} // you can assign ref now without the use of `onFocus`
      />
    );
  }}
/>

// focus will work correct without the `onFocus` prop
<Controller name="test" as={<input />} />

Changed

  • resolver with group error object will no longer need with trigger to show and clear error. This minor version made hook form look at parent error node to detect if there is any group error to show and hide.
const schema = z.object({
  items: z.array(z.boolean()).refine((items) => items.some((item) => item)),
});

{
  items.map((flag, index) => (
    <input
      type="checkbox"
      defaultChecked={false}
      // onChange={() => trigger("items")} now can be removed
      ref={register}
      name={`items.${index}`}
    />
  ));
}

[6.9.0] - 2020-10-3

Changed

  • with shouldUnregister set to false, empty Field Array will default [] as submission result.
const { handleSubmit } = useForm({
  shouldUnregister: false,
});

useFieldArray({
  name: 'test',
});

handleSubmit((data) => {
  // shouldUnregister: false
  // result:  { data: {test: []} }
  // shouldUnregister: true
  // result: {}
});

[6.8.4] - 2020-09-22

Changed

  • when input unmounts touched and dirtyFields will no longer get removed from formState (shouldUnregister: true).

[6.8.0] - 2020-09-09

Added

  • new formState isSubmitSuccessful to indicate successful submission
  • setError now support focus on the actual input
setError('test', { message: 'This is required', shouldFocus: true });

Changed

  • with shouldUnregister:false defaultValues data will be part of the submission data
  • with shouldUnregister:false conditional field is going to work with useFieldArray
  • setValue now support useFieldArray
- setValue('test', 'data')
+ setValue('test', [{ test: '123' }]) // make it work for useFieldArray and target a field array key
  • remove exact config at clearErrors
- clearErrors('test', { exact: false })
+ clearErrors('test') // does it automatically in the lib

[6.7.0] - 2020-08-30

Added

  • clearError have second option argument for clear errors which are exact or key name
register('test.firstName', { required: true });
register('test.lastName', { required: true });
clearErrors('test', { exact: false }); // will clear both errors from test.firstName and test.lastName
clearErrors('test.firstName'); // for clear single input error

[6.6.0] - 2020-08-28

Changed

[6.5.0] - 2020-08-23

Changed

  • errors is also part of formState object
  • disabled input will not be part of the submission data by following the HTML standard

[6.4.0] - 2020-08-15

Added

  • Controller's render prop will pass down name prop
  • handleSubmit take a second callback for errors callback
  • new mode onTouched will only trigger validation after inputs are touched

Changed

  • register no longer compare ref difference with React Native

[6.3.2] - 2020-08-11

Changed

  • IE 11 version will be required to install @babel/runtime-corejs3 as dependency at your own project

[6.3.0] - 2020-08-8

Changed

  • defaultValue is become required for useFieldArray at each input

[6.2.0] - 2020-07-30

Changed

  • revert getValues will return default values before inputs registration

[6.1.0] - 2020-07-26

Changed

  • resolver supports both async and sync
  • getValues will return default values before inputs registration

[6.0.7] - 2020-07-17

Added

  • export ArrayField type

Changed

  • error message will support array of messages for specific type
- export type ValidateResult = Message | boolean | undefined;
+ export type ValidateResult = Message | Message[] | boolean | undefined;

[6.0.3] - 2020-07-10

Changed

  • Controller onFocus works with React Native
  • Controller stop producing checked prop by boolean value

[6.0.2] - 2020-07-8

Added

  • export UseFormOptions, UseFieldArrayOptions, FieldError, Field and Mode type

[6.0.1] - 2020-07-3

Added

  • export ValidationRules type

[6.0.0] - 2020-07-1

Added

  • config for shouldUnregister which allow input to be persist even after unmount
useForm({
  shouldUnregister: false, // unmount input state will be remained
});
  • auto focus with useFieldArray
append({}, (autoFocus = true));
prepend({}, (autoFocus = true));
insert({}, (autoFocus = true));
  • TS: NestedValue
import { useForm, NestedValue } from 'react-hook-form';

type FormValues = {
  key1: string;
  key2: number;
  key3: NestedValue<{
    key1: string;
    key2: number;
  }>;
  key4: NestedValue<string[]>;
};

const { errors } = useForm<FormValues>();

errors?.key1?.message; // no type error
errors?.key2?.message; // no type error
errors?.key3?.message; // no type error
errors?.key4?.message; // no type error
  • useWatch (new) subscribe to registered inputs.
<input name="test" ref={register} />;

function IsolateReRender() {
  const { state } = useWatch({
    name: 'test',
    control,
    defaultValue: 'default',
  });

  return <div>{state}</div>;
}
  • getValues() support array of field names
getValues(['test', 'test1']); // { test: 'test', test1: 'test1' }
  • useForm({ mode: 'all' }) support all validation

Changed

  • rename validationResolver to resolver

  • rename validationContext to context

  • rename validateCriteriaMode to criteriaMode

  • rename triggerValidation to trigger

  • rename clearError to clearErrors

  • rename FormContext to FormProvider

  • rename dirty to isDirty

  • dirtyFields change type from Set to Object

  • Controller with render props API, and removed the following props:

    • onChange
    • onChangeName
    • onBlur
    • onBlurName
    • valueName
-<Controller
-  as={CustomInput}
-  valueName="textValue"
-  onChangeName="onTextChange"
-  control={control}
-  name="test"
-/>
+<Controller
+  render={({ onChange, onBlur, value }) => (
+     <CustomInput onTextChange={onChange} onBlur={onBlur} textValue={value} />
+  )}
+  control={control}
+  name="test"
+/>
  • setError will focus one error at a time and remove confusing set multiple errors, behavior change.
    • setError will persis an error if it's not part of the form, which requires manual remove with clearError
    • setError error will be removed by validation rules, rules always take over errors
- setError('test', 'test', 'test')
+ setError('test', { type: 'test', message: 'bill'})
  • setValue will focus on input at a time
setValue('test', 'value', { shouldValidate: false, shouldDirty: false })

Removed

  • remove validationSchema and embrace validation resolver
  • remove nest option for watch & getValues, so data return from both methods will be in FormValues shape.
-getValues({ nest: true }); // { test: { data: 'test' }}
-watch({ nest: true }); // { test: { data: 'test' }}
+getValues(); // { test: { data: 'test' }}
+watch(); // { test: { data: 'test' }}

[5.0.0] - 2020-03-07

Breaking Change

  • Controller: onChange will only evaluate payload as event like object. eg: react-select will no longer need the extra onChange method at Controller.
import { TextInput } from 'react-native';

-<Controller
-  as={<TextInput style={{ borderWidth: 2, borderColor: 'black'}} />}
-  name="text"
-  control={args => ({
-    value: args[0].nativeEvent.text,
-  })}
-  onChange={onChange}
-/>
+<Controller
+  as={<TextInput style={{ borderWidth: 2, borderColor: 'black'}} />}
+  name="text"
+  control={args => args[0].nativeEvent.text}
+  onChange={onChange}
+/>

[4.0.0] - 2019-12-24

Breaking changes

  • improve module exports:
import { useForm } from 'react-hook-form';
  • nested errors object and better typescript support
type form = {
  yourDetail: {
    firstName: string;
  };
};

errors?.yourDetail?.firstName;
  • triggerValidation argument change from Object, Object[] to String, String[]
triggerValidation('firstName');
triggerValidation(['firstName', 'lastName']);
  • watch support { nest: boolean }
watch(); // { 'test.firstName': 'bill' }
watch({ nest: true }); // { test: { firstName: 'bill' } }
  • improve custom register
register('test', { required: true });
  • setError` support nested object
setError('yourDetail.firstName', 'test');
errors.yourDetails.firstName;
  • handleSubmit no longer rerun array inputs contains undefined or null

Added

  • move RHFInput into the main repo and rename it to Controller
<Controller control={control} name="test" />

Removed

[3.0.0] - 2019-04-21

Added

React Hook Form return a new formState: Object which contain the following information

  • dirty: when user interactive any fields
  • touched: what are the fields have interacted
  • isSubmitted: whether the form have been triggered with submitting
const {
  formState: { dirty, touched, isSubmitted },
} = useForm();

[2.0.0] - 2019-03-29

Added

  • support ref={register} instead of only ref={register()}