@@ -109,7 +109,7 @@ describe('useController', () => {
109
109
110
110
fireEvent . blur ( screen . getAllByRole ( 'textbox' ) [ 0 ] ) ;
111
111
112
- expect ( renderCounter ) . toEqual ( [ 2 , 5 ] ) ;
112
+ expect ( renderCounter ) . toEqual ( [ 2 , 3 ] ) ;
113
113
} ) ;
114
114
115
115
describe ( 'checkbox' , ( ) => {
@@ -1012,4 +1012,96 @@ describe('useController', () => {
1012
1012
} ) ,
1013
1013
) ;
1014
1014
} ) ;
1015
+
1016
+ it ( 'should subscribe to exact form state update' , ( ) => {
1017
+ type FormValues = {
1018
+ test : string ;
1019
+ test_with_suffix : string ;
1020
+ } ;
1021
+
1022
+ const renderCounter : Record < keyof FormValues , number > = {
1023
+ test : 0 ,
1024
+ test_with_suffix : 0 ,
1025
+ } ;
1026
+
1027
+ const ControlledInput = ( {
1028
+ name,
1029
+ control,
1030
+ } : {
1031
+ name : keyof FormValues ;
1032
+ control : Control < FormValues > ;
1033
+ } ) => {
1034
+ const {
1035
+ field,
1036
+ fieldState : { error, isDirty } ,
1037
+ } = useController ( {
1038
+ name,
1039
+ control,
1040
+ rules : { required : 'is required' } ,
1041
+ } ) ;
1042
+
1043
+ renderCounter [ name ] ++ ;
1044
+
1045
+ return (
1046
+ < div >
1047
+ < input aria-label = { name } { ...field } />
1048
+ { error && (
1049
+ < p >
1050
+ { name } { error . message }
1051
+ </ p >
1052
+ ) }
1053
+ { isDirty && < p > { name } isDirty</ p > }
1054
+ </ div >
1055
+ ) ;
1056
+ } ;
1057
+
1058
+ const App = ( ) => {
1059
+ const { control } = useForm < FormValues > ( {
1060
+ mode : 'onBlur' ,
1061
+ defaultValues : {
1062
+ test : '1234' ,
1063
+ test_with_suffix : '1234' ,
1064
+ } ,
1065
+ } ) ;
1066
+ return (
1067
+ < form >
1068
+ < ControlledInput name = "test" control = { control } />
1069
+ < ControlledInput name = "test_with_suffix" control = { control } />
1070
+ </ form >
1071
+ ) ;
1072
+ } ;
1073
+
1074
+ render ( < App /> ) ;
1075
+
1076
+ expect ( renderCounter ) . toEqual ( { test : 1 , test_with_suffix : 1 } ) ;
1077
+ expect ( screen . queryByText ( 'test is required' ) ) . toBeNull ( ) ;
1078
+ expect ( screen . queryByText ( 'test_with_suffix is required' ) ) . toBeNull ( ) ;
1079
+
1080
+ fireEvent . change ( screen . getByRole ( 'textbox' , { name : 'test' } ) , {
1081
+ target : {
1082
+ value : '' ,
1083
+ } ,
1084
+ } ) ;
1085
+
1086
+ fireEvent . blur ( screen . getByRole ( 'textbox' , { name : 'test' } ) ) ;
1087
+
1088
+ expect ( screen . getByText ( 'test isDirty' ) ) . toBeVisible ( ) ;
1089
+
1090
+ expect ( renderCounter ) . toEqual ( { test : 2 , test_with_suffix : 1 } ) ;
1091
+
1092
+ fireEvent . change (
1093
+ screen . getByRole ( 'textbox' , { name : 'test_with_suffix' } ) ,
1094
+ {
1095
+ target : {
1096
+ value : '' ,
1097
+ } ,
1098
+ } ,
1099
+ ) ;
1100
+
1101
+ fireEvent . blur ( screen . getByRole ( 'textbox' , { name : 'test_with_suffix' } ) ) ;
1102
+
1103
+ expect ( screen . getByText ( 'test_with_suffix isDirty' ) ) . toBeVisible ( ) ;
1104
+
1105
+ expect ( renderCounter ) . toEqual ( { test : 2 , test_with_suffix : 2 } ) ;
1106
+ } ) ;
1015
1107
} ) ;
0 commit comments