import { useState , useEffect } from 'react' ; import { useForm } from 'react-final-form' ; import isEqual from 'lodash/isEqual' ; import { useFormContext } from './useFormContext' ; import { FieldState } from 'final-form' ; type FormGroupState = { dirty : boolean ; errors : object ; invalid : boolean ; pristine : boolean ; touched : boolean ; valid : boolean ; } ; example param { string } name returns { FormGroupState } export const useFormGroup = ( name ) : FormGroupState => { const form = useForm ( ) ; const formContext = useFormContext ( ) ; const [ state , setState ] = useState < FormGroupState > ( { dirty : false , errors : undefined , invalid : false , pristine : true , touched : false , valid : true , } ) ; useEffect ( ( ) => { const unsubscribe = form . subscribe ( ( ) => { const fields = formContext . getGroupFields ( name ) ; const fieldStates = fields . map ( field => { return form . getFieldState ( field ) ; } ) . filter ( fieldState => fieldState != undefined ) ; const newState = getFormGroupState ( fieldStates ) ; setState ( oldState => { if ( ! isEqual ( oldState , newState ) ) { return newState ; } return oldState ; } ) ; } , { errors : true , invalid : true , dirty : true , pristine : true , valid : true , touched : true , } ) ; return unsubscribe ; } , [ form , formContext , name ] ) ; return state ; } ; param { FieldState [ ] } fieldStates returns { FormGroupState } export const getFormGroupState = ( fieldStates ) : FormGroupState => { return fieldStates . reduce ( ( acc , fieldState ) => { let errors = acc . errors || { } ; if ( fieldState . error ) { errors [ fieldState . name ] = fieldState . error ; } const newState = { dirty : acc . dirty || fieldState . dirty , errors , invalid : acc . invalid || fieldState . invalid , pristine : acc . pristine && fieldState . pristine , touched : acc . touched || fieldState . touched , valid : acc . valid && fieldState . valid , } ; return newState ; } , { dirty : false , errors : undefined , invalid : false , pristine : true , valid : true , touched : false , } ) ; } ;