/
githubmirror
/
react-hook-form
Обзор
Документация
Войти
/
githubmirror
/
react-hook-form
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/useFormState.ts
121 строка
3 KB
Bill
🛹 feat: support `<Activity />` (#13633)
06 авг 2026, 14:12
Не верифицирован
06 авг 2026, 14:12
9fde5f3
Код
Авторство
О чём код?
import React from 'react'; import getProxyFormState from './logic/getProxyFormState'; import type { FieldValues, FormState, UseFormStateProps, UseFormStateReturn, } from './types'; import { useFormControlContext } from './useFormControlContext'; import { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'; import { useResyncOnReconnect } from './useResyncOnReconnect'; /** * Subscribes to each form state and isolates re-renders at the custom hook level. It has its own scope for form state subscriptions, so it will not affect other useFormState or useForm instances. Using this hook can reduce the re-render impact on large and complex form applications. * * @remarks * [API](https://react-hook-form.com/docs/useformstate) • [Demo](https://codesandbox.io/s/useformstate-75xly) * * @param props - Include options to specify fields to subscribe to. {@link UseFormStateReturn} * * @example * ```tsx * function App() { * const { register, handleSubmit, control } = useForm({ * defaultValues: { * firstName: "firstName" * }}); * const { dirtyFields } = useFormState({ * control * }); * const onSubmit = (data) => console.log(data); * * return ( * <form onSubmit={handleSubmit(onSubmit)}> * <input {...register("firstName")} placeholder="First Name" /> * {dirtyFields.firstName && <p>Field is dirty.</p>} * <input type="submit" /> * </form> * ); * } * ``` */ export function useFormState< TFieldValues extends FieldValues = FieldValues, TTransformedValues = TFieldValues, >( props?: UseFormStateProps<TFieldValues, TTransformedValues>, ): UseFormStateReturn<TFieldValues> { const formControl = useFormControlContext< TFieldValues, any, TTransformedValues >(); const { control = formControl, disabled, name, exact } = props || {}; const [formState, updateFormState] = React.useState<FormState<TFieldValues>>( () => ({ ...control._formState, defaultValues: control._defaultValues as FormState<TFieldValues>['defaultValues'], }), ); const _localProxyFormState = React.useRef({ isDirty: false, isLoading: false, dirtyFields: false, touchedFields: false, validatingFields: false, isValidating: false, isValid: false, errors: false, }); const { resyncIfNeeded, snapshot } = useResyncOnReconnect<FormState<TFieldValues>>(); useIsomorphicLayoutEffect(() => { const getCurrentFormState = () => ({ ...control._formState, defaultValues: control._defaultValues as FormState<TFieldValues>['defaultValues'], }); resyncIfNeeded(!disabled, getCurrentFormState, updateFormState); const unsubscribe = control._subscribe({ name, formState: _localProxyFormState.current, exact, callback: (formState) => { !disabled && updateFormState({ ...control._formState, ...formState, defaultValues: control._defaultValues as FormState<TFieldValues>['defaultValues'], }); }, }); return () => { unsubscribe(); snapshot(!disabled, getCurrentFormState); }; }, [name, disabled, exact, resyncIfNeeded, snapshot]); React.useEffect(() => { _localProxyFormState.current.isValid && control._setValid(true); }, [control]); return React.useMemo( () => getProxyFormState( formState, control, _localProxyFormState.current, false, ), [formState, control], ); }