11import * as React from 'react' ;
22import 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' ;
44import FieldContext from './FieldContext' ;
55import Field from './Field' ;
66import { move , getNamePath } from './utils/valueUtil' ;
7+ import type { ListContextProps } from './ListContext' ;
8+ import ListContext from './ListContext' ;
79
810export interface ListField {
911 name : number ;
@@ -43,15 +45,31 @@ const List: React.FunctionComponent<ListProps> = ({
4345 } ) ;
4446 const keyManager = keyRef . current ;
4547
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+
4667 // User should not pass `children` as other type.
4768 if ( typeof children !== 'function' ) {
4869 warning ( false , 'Form.List only accepts function as children.' ) ;
4970 return null ;
5071 }
5172
52- const parentPrefixName = getNamePath ( context . prefixName ) || [ ] ;
53- const prefixName : InternalNamePath = [ ...parentPrefixName , ...getNamePath ( name ) ] ;
54-
5573 const shouldUpdate = ( prevValue : StoreValue , nextValue : StoreValue , { source } ) => {
5674 if ( source === 'internal' ) {
5775 return false ;
@@ -60,93 +78,98 @@ const List: React.FunctionComponent<ListProps> = ({
6078 } ;
6179
6280 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 ] ) ;
102124 }
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 ] ) ;
125130
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+ ) ;
130137
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+ }
132151
133- // Trigger store change
134- onChange ( move ( newValue , from , to ) ) ;
135- } ,
136- } ;
152+ keyManager . keys = move ( keyManager . keys , from , to ) ;
137153
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 = [ ] ;
141162
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+ }
144169 }
145- }
146170
147- return children (
148- ( listValue as StoreValue [ ] ) . map (
149- ( __ , index ) : ListField => {
171+ return children (
172+ ( listValue as StoreValue [ ] ) . map ( ( __ , index ) : ListField => {
150173 let key = keyManager . keys [ index ] ;
151174 if ( key === undefined ) {
152175 keyManager . keys [ index ] = keyManager . id ;
@@ -159,14 +182,14 @@ const List: React.FunctionComponent<ListProps> = ({
159182 key,
160183 isListField : true ,
161184 } ;
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 >
170193 ) ;
171194} ;
172195
0 commit comments