@@ -29,18 +29,67 @@ export type DeepStateShowComponent<
2929 ) => boolean ;
3030} ) => React . ReactElement < any , any > | null ;
3131
32+ export type DeepStateWatchComponent <
33+ FormFieldTypes extends InferForm < Form < any > > = InferForm < Form < any > > ,
34+ GraphTypes extends Record < keyof GraphTypes , keyof FormFieldTypes > = Record <
35+ string ,
36+ keyof FormFieldTypes
37+ > ,
38+ > = < DependencyKeys extends Array < keyof GraphTypes | '_meta' > > ( props : {
39+ keys : DependencyKeys ;
40+ children : (
41+ data : DependencyData < FormFieldTypes , GraphTypes , DependencyKeys > ,
42+ ) => React . ReactElement < any , any > | null ;
43+ } ) => React . ReactElement < any , any > | null ;
44+
3245export const buildComponents = < Config extends Form < Record < string , any > > > (
3346 formConfig : Config ,
3447) => {
48+ const validateKeys = (
49+ type : 'Field' | 'Show' | 'Watch' ,
50+ keys : Array < string > ,
51+ keyToTypeMap : Record < string , string > ,
52+ ) => {
53+ for ( const key of keys ) {
54+ if ( key === '_meta' ) continue ;
55+
56+ if ( ! keyToTypeMap [ key ] ) {
57+ throw new Error (
58+ `To use the ${ type } component, the field key \`${ key } \` must be set in the <FormProvider> fields prop.` ,
59+ ) ;
60+ }
61+ }
62+ } ;
63+
64+ const useWatchFields = < Keys extends Array < string | number | symbol > > (
65+ keys : Keys ,
66+ ) => {
67+ const selector = useDeepStateSelector (
68+ ...keys . map < DeepStateSelector > ( ( key ) => {
69+ return ( state ) => state [ key as keyof typeof state ] ;
70+ } ) ,
71+ ) ;
72+
73+ const { data, config } = useDeepState ( { selector } ) ;
74+
75+ type DataMap = DependencyData <
76+ InferForm < Form < any > > ,
77+ Record < string , keyof InferForm < Form < any > > > ,
78+ Keys
79+ > ;
80+
81+ const dataMap = keys . reduce < DataMap > (
82+ ( acc , key , index ) => ( { ...acc , [ key ] : data [ index ] } ) ,
83+ { } as DataMap ,
84+ ) ;
85+
86+ return { dataMap, config } ;
87+ } ;
88+
3589 const DeepStateField : DeepStateFieldComponent = ( { field, children } ) => {
36- const {
37- data : props ,
38- config : { keyToTypeMap } ,
39- } = useDeepState ( {
40- selector : ( state ) => state [ field ] ,
41- } ) ;
42-
43- const fieldType = keyToTypeMap [ field ] ;
90+ const { dataMap, config } = useWatchFields ( [ field ] ) ;
91+
92+ const fieldType = config . keyToTypeMap [ field ] ;
4493 if ( ! fieldType ) {
4594 throw new Error (
4695 `Field key ${ field } must be set in the <FormProvider> fields prop.` ,
@@ -50,42 +99,25 @@ export const buildComponents = <Config extends Form<Record<string, any>>>(
5099 const Component = formConfig . _fields [ fieldType ] . _component ;
51100
52101 return typeof children === 'function' ? (
53- children ( props )
102+ children ( dataMap [ field as keyof typeof dataMap ] )
54103 ) : (
55104 // TODO: Fix the type for Fields/BaseConfigs
56105 // StoreSnapshot is wrong
57- < Component { ...( props as any ) } />
106+ < Component { ...dataMap [ field as keyof typeof dataMap ] } />
58107 ) ;
59108 } ;
60109
61110 const DeepStateShow : DeepStateShowComponent = ( { children, keys, when } ) => {
62- const selector = useDeepStateSelector (
63- ...keys . map < DeepStateSelector > ( ( key ) => {
64- return ( state ) => state [ key as keyof typeof state ] ;
65- } ) ,
66- ) ;
67-
68- const {
69- data,
70- config : { keyToTypeMap } ,
71- } = useDeepState ( { selector } ) ;
72-
73- for ( const key of keys ) {
74- if ( key === '_meta' ) continue ;
75-
76- if ( ! keyToTypeMap [ key ] ) {
77- throw new Error (
78- `To use the Show component. the Field key ${ key } must be set in the <FormProvider> fields prop.` ,
79- ) ;
80- }
81- }
82-
83- const dataMap = keys . reduce <
84- DependencyData < Record < string , any > , Record < string , any > , Array < any > >
85- > ( ( acc , key , index ) => ( { ...acc , [ key ] : data [ index ] } ) , { } ) ;
86-
111+ const { dataMap, config } = useWatchFields ( keys ) ;
112+ validateKeys ( 'Show' , keys , config . keyToTypeMap ) ;
87113 return when ( dataMap ) ? children : null ;
88114 } ;
89115
90- return { Field : DeepStateField , Show : DeepStateShow } ;
116+ const DeepStateWatch : DeepStateWatchComponent = ( { children, keys } ) => {
117+ const { dataMap, config } = useWatchFields ( keys ) ;
118+ validateKeys ( 'Watch' , keys , config . keyToTypeMap ) ;
119+ return children ( dataMap ) ;
120+ } ;
121+
122+ return { Field : DeepStateField , Show : DeepStateShow , Watch : DeepStateWatch } ;
91123} ;
0 commit comments