react-hook-form 7.70.0 → 7.71.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -123,73 +123,16 @@ const INPUT_VALIDATION_RULES = {
123
123
  validate: 'validate',
124
124
  };
125
125
 
126
- const HookFormContext = React.createContext(null);
127
- HookFormContext.displayName = 'HookFormContext';
128
126
  /**
129
- * This custom hook allows you to access the form context. useFormContext is intended to be used in deeply nested structures, where it would become inconvenient to pass the context as a prop. To be used with {@link FormProvider}.
130
- *
131
- * @remarks
132
- * [API](https://react-hook-form.com/docs/useformcontext) • [Demo](https://codesandbox.io/s/react-hook-form-v7-form-context-ytudi)
133
- *
134
- * @returns return all useForm methods
135
- *
136
- * @example
137
- * ```tsx
138
- * function App() {
139
- * const methods = useForm();
140
- * const onSubmit = data => console.log(data);
141
- *
142
- * return (
143
- * <FormProvider {...methods} >
144
- * <form onSubmit={methods.handleSubmit(onSubmit)}>
145
- * <NestedInput />
146
- * <input type="submit" />
147
- * </form>
148
- * </FormProvider>
149
- * );
150
- * }
151
- *
152
- * function NestedInput() {
153
- * const { register } = useFormContext(); // retrieve all hook methods
154
- * return <input {...register("test")} />;
155
- * }
156
- * ```
127
+ * Separate context for `control` to prevent unnecessary rerenders.
128
+ * Internal hooks that only need control use this instead of full form context.
157
129
  */
158
- const useFormContext = () => React.useContext(HookFormContext);
130
+ const HookFormControlContext = React.createContext(null);
131
+ HookFormControlContext.displayName = 'HookFormControlContext';
159
132
  /**
160
- * A provider component that propagates the `useForm` methods to all children components via [React Context](https://react.dev/reference/react/useContext) API. To be used with {@link useFormContext}.
161
- *
162
- * @remarks
163
- * [API](https://react-hook-form.com/docs/useformcontext) • [Demo](https://codesandbox.io/s/react-hook-form-v7-form-context-ytudi)
164
- *
165
- * @param props - all useForm methods
166
- *
167
- * @example
168
- * ```tsx
169
- * function App() {
170
- * const methods = useForm();
171
- * const onSubmit = data => console.log(data);
172
- *
173
- * return (
174
- * <FormProvider {...methods} >
175
- * <form onSubmit={methods.handleSubmit(onSubmit)}>
176
- * <NestedInput />
177
- * <input type="submit" />
178
- * </form>
179
- * </FormProvider>
180
- * );
181
- * }
182
- *
183
- * function NestedInput() {
184
- * const { register } = useFormContext(); // retrieve all hook methods
185
- * return <input {...register("test")} />;
186
- * }
187
- * ```
133
+ * @internal Internal hook to access only control from context.
188
134
  */
189
- const FormProvider = (props) => {
190
- const { children, ...data } = props;
191
- return (React.createElement(HookFormContext.Provider, { value: data }, children));
192
- };
135
+ const useFormControlContext = () => React.useContext(HookFormControlContext);
193
136
 
194
137
  var getProxyFormState = (formState, control, localProxyFormState, isRoot = true) => {
195
138
  const result = {
@@ -243,8 +186,8 @@ const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? React.useLayou
243
186
  * ```
244
187
  */
245
188
  function useFormState(props) {
246
- const methods = useFormContext();
247
- const { control = methods.control, disabled, name, exact } = props || {};
189
+ const formControl = useFormControlContext();
190
+ const { control = formControl, disabled, name, exact } = props || {};
248
191
  const [formState, updateFormState] = React.useState(control._formState);
249
192
  const _localProxyFormState = React.useRef({
250
193
  isDirty: false,
@@ -344,8 +287,8 @@ function deepEqual(object1, object2, _internal_visited = new WeakSet()) {
344
287
  * ```
345
288
  */
346
289
  function useWatch(props) {
347
- const methods = useFormContext();
348
- const { control = methods.control, name, defaultValue, disabled, exact, compute, } = props || {};
290
+ const formControl = useFormControlContext();
291
+ const { control = formControl, name, defaultValue, disabled, exact, compute, } = props || {};
349
292
  const _defaultValue = React.useRef(defaultValue);
350
293
  const _compute = React.useRef(compute);
351
294
  const _computeFormValues = React.useRef(undefined);
@@ -438,8 +381,8 @@ function useWatch(props) {
438
381
  * ```
439
382
  */
440
383
  function useController(props) {
441
- const methods = useFormContext();
442
- const { name, disabled, control = methods.control, shouldUnregister, defaultValue, exact = true, } = props;
384
+ const formControl = useFormControlContext();
385
+ const { name, disabled, control = formControl, shouldUnregister, defaultValue, exact = true, } = props;
443
386
  const isArrayField = isNameInFieldArray(control._names.array, name);
444
387
  const defaultValueMemo = React.useMemo(() => get(control._formValues, name, get(control._defaultValues, name, defaultValue)), [control, name, defaultValue]);
445
388
  const value = useWatch({
@@ -627,6 +570,109 @@ const flatten = (obj) => {
627
570
  return output;
628
571
  };
629
572
 
573
+ const HookFormContext = React.createContext(null);
574
+ HookFormContext.displayName = 'HookFormContext';
575
+ /**
576
+ * This custom hook allows you to access the form context. useFormContext is intended to be used in deeply nested structures, where it would become inconvenient to pass the context as a prop. To be used with {@link FormProvider}.
577
+ *
578
+ * @remarks
579
+ * [API](https://react-hook-form.com/docs/useformcontext) • [Demo](https://codesandbox.io/s/react-hook-form-v7-form-context-ytudi)
580
+ *
581
+ * @returns return all useForm methods
582
+ *
583
+ * @example
584
+ * ```tsx
585
+ * function App() {
586
+ * const methods = useForm();
587
+ * const onSubmit = data => console.log(data);
588
+ *
589
+ * return (
590
+ * <FormProvider {...methods} >
591
+ * <form onSubmit={methods.handleSubmit(onSubmit)}>
592
+ * <NestedInput />
593
+ * <input type="submit" />
594
+ * </form>
595
+ * </FormProvider>
596
+ * );
597
+ * }
598
+ *
599
+ * function NestedInput() {
600
+ * const { register } = useFormContext(); // retrieve all hook methods
601
+ * return <input {...register("test")} />;
602
+ * }
603
+ * ```
604
+ */
605
+ const useFormContext = () => React.useContext(HookFormContext);
606
+ /**
607
+ * A provider component that propagates the `useForm` methods to all children components via [React Context](https://react.dev/reference/react/useContext) API. To be used with {@link useFormContext}.
608
+ *
609
+ * @remarks
610
+ * [API](https://react-hook-form.com/docs/useformcontext) • [Demo](https://codesandbox.io/s/react-hook-form-v7-form-context-ytudi)
611
+ *
612
+ * @param props - all useForm methods
613
+ *
614
+ * @example
615
+ * ```tsx
616
+ * function App() {
617
+ * const methods = useForm();
618
+ * const onSubmit = data => console.log(data);
619
+ *
620
+ * return (
621
+ * <FormProvider {...methods} >
622
+ * <form onSubmit={methods.handleSubmit(onSubmit)}>
623
+ * <NestedInput />
624
+ * <input type="submit" />
625
+ * </form>
626
+ * </FormProvider>
627
+ * );
628
+ * }
629
+ *
630
+ * function NestedInput() {
631
+ * const { register } = useFormContext(); // retrieve all hook methods
632
+ * return <input {...register("test")} />;
633
+ * }
634
+ * ```
635
+ */
636
+ const FormProvider = (props) => {
637
+ const { children, watch, getValues, getFieldState, setError, clearErrors, setValue, trigger, formState, resetField, reset, handleSubmit, unregister, control, register, setFocus, subscribe, } = props;
638
+ return (React.createElement(HookFormContext.Provider, { value: React.useMemo(() => ({
639
+ watch,
640
+ getValues,
641
+ getFieldState,
642
+ setError,
643
+ clearErrors,
644
+ setValue,
645
+ trigger,
646
+ formState,
647
+ resetField,
648
+ reset,
649
+ handleSubmit,
650
+ unregister,
651
+ control,
652
+ register,
653
+ setFocus,
654
+ subscribe,
655
+ }), [
656
+ clearErrors,
657
+ control,
658
+ formState,
659
+ getFieldState,
660
+ getValues,
661
+ handleSubmit,
662
+ register,
663
+ reset,
664
+ resetField,
665
+ setError,
666
+ setFocus,
667
+ setValue,
668
+ subscribe,
669
+ trigger,
670
+ unregister,
671
+ watch,
672
+ ]) },
673
+ React.createElement(HookFormControlContext.Provider, { value: control }, children)));
674
+ };
675
+
630
676
  const POST_REQUEST = 'post';
631
677
  /**
632
678
  * Form component to manage submission.
@@ -2004,7 +2050,11 @@ function createFormControl(props = {}) {
2004
2050
  if ((isBoolean(disabled) && _state.mount) ||
2005
2051
  !!disabled ||
2006
2052
  _names.disabled.has(name)) {
2053
+ const wasDisabled = _names.disabled.has(name);
2054
+ const isDisabled = !!disabled;
2055
+ const disabledStateChanged = wasDisabled !== isDisabled;
2007
2056
  disabled ? _names.disabled.add(name) : _names.disabled.delete(name);
2057
+ disabledStateChanged && _state.mount && !_state.action && _setValid();
2008
2058
  }
2009
2059
  };
2010
2060
  const register = (name, options = {}) => {
@@ -2535,8 +2585,8 @@ var updateAt = (fieldValues, index, value) => {
2535
2585
  * ```
2536
2586
  */
2537
2587
  function useFieldArray(props) {
2538
- const methods = useFormContext();
2539
- const { control = methods.control, name, keyName = 'id', shouldUnregister, rules, } = props;
2588
+ const formControl = useFormControlContext();
2589
+ const { control = formControl, name, keyName = 'id', shouldUnregister, rules, } = props;
2540
2590
  const [fields, setFields] = React.useState(control._getFieldArray(name));
2541
2591
  const ids = React.useRef(control._getFieldArray(name).map(generateId));
2542
2592
  const _actioned = React.useRef(false);
@@ -2878,7 +2928,7 @@ function useForm(props = {}) {
2878
2928
  }
2879
2929
  control._removeUnmounted();
2880
2930
  });
2881
- _formControl.current.formState = getProxyFormState(formState, control);
2931
+ _formControl.current.formState = React.useMemo(() => getProxyFormState(formState, control), [control, formState]);
2882
2932
  return _formControl.current;
2883
2933
  }
2884
2934