1
1
import * as React from 'react' ;
2
2
import warning from 'rc-util/lib/warning' ;
3
- import { InternalNamePath , NamePath , StoreValue , ValidatorRule , Meta } from './interface' ;
3
+ import type { InternalNamePath , NamePath , StoreValue , ValidatorRule , Meta } from './interface' ;
4
4
import FieldContext from './FieldContext' ;
5
5
import Field from './Field' ;
6
6
import { move , getNamePath } from './utils/valueUtil' ;
7
+ import type { ListContextProps } from './ListContext' ;
8
+ import ListContext from './ListContext' ;
7
9
8
10
export interface ListField {
9
11
name : number ;
@@ -43,15 +45,31 @@ const List: React.FunctionComponent<ListProps> = ({
43
45
} ) ;
44
46
const keyManager = keyRef . current ;
45
47
48
+ const prefixName : InternalNamePath = React . useMemo ( ( ) => {
49
+ const parentPrefixName = getNamePath ( context . prefixName ) || [ ] ;
50
+ return [ ...parentPrefixName , ...getNamePath ( name ) ] ;
51
+ } , [ context . prefixName , name ] ) ;
52
+
53
+ const fieldContext = React . useMemo ( ( ) => ( { ...context , prefixName } ) , [ context , prefixName ] ) ;
54
+
55
+ // List context
56
+ const listContext = React . useMemo < ListContextProps > (
57
+ ( ) => ( {
58
+ getKey : ( namePath : InternalNamePath ) => {
59
+ const len = prefixName . length ;
60
+ const pathName = namePath [ len ] ;
61
+ return keyManager . keys [ pathName ] ;
62
+ } ,
63
+ } ) ,
64
+ [ prefixName ] ,
65
+ ) ;
66
+
46
67
// User should not pass `children` as other type.
47
68
if ( typeof children !== 'function' ) {
48
69
warning ( false , 'Form.List only accepts function as children.' ) ;
49
70
return null ;
50
71
}
51
72
52
- const parentPrefixName = getNamePath ( context . prefixName ) || [ ] ;
53
- const prefixName : InternalNamePath = [ ...parentPrefixName , ...getNamePath ( name ) ] ;
54
-
55
73
const shouldUpdate = ( prevValue : StoreValue , nextValue : StoreValue , { source } ) => {
56
74
if ( source === 'internal' ) {
57
75
return false ;
@@ -60,93 +78,98 @@ const List: React.FunctionComponent<ListProps> = ({
60
78
} ;
61
79
62
80
return (
63
- < FieldContext . Provider value = { { ...context , prefixName } } >
64
- < Field
65
- name = { [ ] }
66
- shouldUpdate = { shouldUpdate }
67
- rules = { rules }
68
- validateTrigger = { validateTrigger }
69
- initialValue = { initialValue }
70
- isList
71
- >
72
- { ( { value = [ ] , onChange } , meta ) => {
73
- const { getFieldValue } = context ;
74
- const getNewValue = ( ) => {
75
- const values = getFieldValue ( prefixName || [ ] ) as StoreValue [ ] ;
76
- return values || [ ] ;
77
- } ;
78
- /**
79
- * Always get latest value in case user update fields by `form` api.
80
- */
81
- const operations : ListOperations = {
82
- add : ( defaultValue , index ?: number ) => {
83
- // Mapping keys
84
- const newValue = getNewValue ( ) ;
85
-
86
- if ( index >= 0 && index <= newValue . length ) {
87
- keyManager . keys = [
88
- ...keyManager . keys . slice ( 0 , index ) ,
89
- keyManager . id ,
90
- ...keyManager . keys . slice ( index ) ,
91
- ] ;
92
- onChange ( [ ...newValue . slice ( 0 , index ) , defaultValue , ...newValue . slice ( index ) ] ) ;
93
- } else {
94
- if (
95
- process . env . NODE_ENV !== 'production' &&
96
- ( index < 0 || index > newValue . length )
97
- ) {
98
- warning (
99
- false ,
100
- 'The second parameter of the add function should be a valid positive number.' ,
101
- ) ;
81
+ < ListContext . Provider value = { listContext } >
82
+ < FieldContext . Provider value = { fieldContext } >
83
+ < Field
84
+ name = { [ ] }
85
+ shouldUpdate = { shouldUpdate }
86
+ rules = { rules }
87
+ validateTrigger = { validateTrigger }
88
+ initialValue = { initialValue }
89
+ isList
90
+ >
91
+ { ( { value = [ ] , onChange } , meta ) => {
92
+ const { getFieldValue } = context ;
93
+ const getNewValue = ( ) => {
94
+ const values = getFieldValue ( prefixName || [ ] ) as StoreValue [ ] ;
95
+ return values || [ ] ;
96
+ } ;
97
+ /**
98
+ * Always get latest value in case user update fields by `form` api.
99
+ */
100
+ const operations : ListOperations = {
101
+ add : ( defaultValue , index ?: number ) => {
102
+ // Mapping keys
103
+ const newValue = getNewValue ( ) ;
104
+
105
+ if ( index >= 0 && index <= newValue . length ) {
106
+ keyManager . keys = [
107
+ ...keyManager . keys . slice ( 0 , index ) ,
108
+ keyManager . id ,
109
+ ...keyManager . keys . slice ( index ) ,
110
+ ] ;
111
+ onChange ( [ ...newValue . slice ( 0 , index ) , defaultValue , ...newValue . slice ( index ) ] ) ;
112
+ } else {
113
+ if (
114
+ process . env . NODE_ENV !== 'production' &&
115
+ ( index < 0 || index > newValue . length )
116
+ ) {
117
+ warning (
118
+ false ,
119
+ 'The second parameter of the add function should be a valid positive number.' ,
120
+ ) ;
121
+ }
122
+ keyManager . keys = [ ...keyManager . keys , keyManager . id ] ;
123
+ onChange ( [ ...newValue , defaultValue ] ) ;
102
124
}
103
- keyManager . keys = [ ...keyManager . keys , keyManager . id ] ;
104
- onChange ( [ ...newValue , defaultValue ] ) ;
105
- }
106
- keyManager . id += 1 ;
107
- } ,
108
- remove : ( index : number | number [ ] ) => {
109
- const newValue = getNewValue ( ) ;
110
- const indexSet = new Set ( Array . isArray ( index ) ? index : [ index ] ) ;
111
-
112
- if ( indexSet . size <= 0 ) {
113
- return ;
114
- }
115
- keyManager . keys = keyManager . keys . filter ( ( _ , keysIndex ) => ! indexSet . has ( keysIndex ) ) ;
116
-
117
- // Trigger store change
118
- onChange ( newValue . filter ( ( _ , valueIndex ) => ! indexSet . has ( valueIndex ) ) ) ;
119
- } ,
120
- move ( from : number , to : number ) {
121
- if ( from === to ) {
122
- return ;
123
- }
124
- const newValue = getNewValue ( ) ;
125
+ keyManager . id += 1 ;
126
+ } ,
127
+ remove : ( index : number | number [ ] ) => {
128
+ const newValue = getNewValue ( ) ;
129
+ const indexSet = new Set ( Array . isArray ( index ) ? index : [ index ] ) ;
125
130
126
- // Do not handle out of range
127
- if ( from < 0 || from >= newValue . length || to < 0 || to >= newValue . length ) {
128
- return ;
129
- }
131
+ if ( indexSet . size <= 0 ) {
132
+ return ;
133
+ }
134
+ keyManager . keys = keyManager . keys . filter (
135
+ ( _ , keysIndex ) => ! indexSet . has ( keysIndex ) ,
136
+ ) ;
130
137
131
- keyManager . keys = move ( keyManager . keys , from , to ) ;
138
+ // Trigger store change
139
+ onChange ( newValue . filter ( ( _ , valueIndex ) => ! indexSet . has ( valueIndex ) ) ) ;
140
+ } ,
141
+ move ( from : number , to : number ) {
142
+ if ( from === to ) {
143
+ return ;
144
+ }
145
+ const newValue = getNewValue ( ) ;
146
+
147
+ // Do not handle out of range
148
+ if ( from < 0 || from >= newValue . length || to < 0 || to >= newValue . length ) {
149
+ return ;
150
+ }
132
151
133
- // Trigger store change
134
- onChange ( move ( newValue , from , to ) ) ;
135
- } ,
136
- } ;
152
+ keyManager . keys = move ( keyManager . keys , from , to ) ;
137
153
138
- let listValue = value || [ ] ;
139
- if ( ! Array . isArray ( listValue ) ) {
140
- listValue = [ ] ;
154
+ // Trigger store change
155
+ onChange ( move ( newValue , from , to ) ) ;
156
+ } ,
157
+ } ;
158
+
159
+ let listValue = value || [ ] ;
160
+ if ( ! Array . isArray ( listValue ) ) {
161
+ listValue = [ ] ;
141
162
142
- if ( process . env . NODE_ENV !== 'production' ) {
143
- warning ( false , `Current value of '${ prefixName . join ( ' > ' ) } ' is not an array type.` ) ;
163
+ if ( process . env . NODE_ENV !== 'production' ) {
164
+ warning (
165
+ false ,
166
+ `Current value of '${ prefixName . join ( ' > ' ) } ' is not an array type.` ,
167
+ ) ;
168
+ }
144
169
}
145
- }
146
170
147
- return children (
148
- ( listValue as StoreValue [ ] ) . map (
149
- ( __ , index ) : ListField => {
171
+ return children (
172
+ ( listValue as StoreValue [ ] ) . map ( ( __ , index ) : ListField => {
150
173
let key = keyManager . keys [ index ] ;
151
174
if ( key === undefined ) {
152
175
keyManager . keys [ index ] = keyManager . id ;
@@ -159,14 +182,14 @@ const List: React.FunctionComponent<ListProps> = ({
159
182
key,
160
183
isListField : true ,
161
184
} ;
162
- } ,
163
- ) ,
164
- operations ,
165
- meta ,
166
- ) ;
167
- } }
168
- </ Field >
169
- </ FieldContext . Provider >
185
+ } ) ,
186
+ operations ,
187
+ meta ,
188
+ ) ;
189
+ } }
190
+ </ Field >
191
+ </ FieldContext . Provider >
192
+ </ ListContext . Provider >
170
193
) ;
171
194
} ;
172
195
0 commit comments