@@ -14,6 +14,7 @@ import type { FormContextProps } from './FormContext';
1414import  FormContext  from  './FormContext' ; 
1515import  {  isSimilar  }  from  './utils/valueUtil' ; 
1616import  ListContext  from  './ListContext' ; 
17+ import  BatchUpdate ,  {  BatchTask ,  type  BatchUpdateRef  }  from  './BatchUpdate' ; 
1718
1819type  BaseFormProps  =  Omit < React . FormHTMLAttributes < HTMLFormElement > ,  'onSubmit'  |  'children' > ; 
1920
@@ -70,6 +71,7 @@ const Form: React.ForwardRefRenderFunction<FormRef, FormProps> = (
7071    setValidateMessages, 
7172    setPreserve, 
7273    destroyForm, 
74+     setBatchUpdate, 
7375  }  =  ( formInstance  as  InternalFormInstance ) . getInternalHooks ( HOOK_MARK ) ; 
7476
7577  // Pass ref with form instance 
@@ -118,6 +120,42 @@ const Form: React.ForwardRefRenderFunction<FormRef, FormProps> = (
118120    mountRef . current  =  true ; 
119121  } 
120122
123+   // ======================== Batch Update ======================== 
124+   // zombieJ: 
125+   // To avoid Form self re-render, 
126+   // We create a sub component `BatchUpdate` to handle batch update logic. 
127+   // When the call with do not change immediate, we will batch the update 
128+   // and flush it in `useLayoutEffect` for next tick. 
129+ 
130+   // Set batch update ref 
131+   const  batchUpdateRef  =  React . useRef < BatchUpdateRef > ( null ) ; 
132+   const  batchUpdateTasksRef  =  React . useRef < [ key : string ,  fn : VoidFunction ] [ ] > ( [ ] ) ; 
133+ 
134+   const  tryFlushBatch  =  ( )  =>  { 
135+     if  ( batchUpdateRef . current )  { 
136+       batchUpdateTasksRef . current . forEach ( ( [ key ,  fn ] )  =>  { 
137+         batchUpdateRef . current . batch ( key ,  fn ) ; 
138+       } ) ; 
139+       batchUpdateTasksRef . current  =  [ ] ; 
140+     } 
141+   } ; 
142+ 
143+   // Ref update 
144+   const  setBatchUpdateRef  =  React . useCallback ( ( batchUpdate : BatchUpdateRef  |  null )  =>  { 
145+     batchUpdateRef . current  =  batchUpdate ; 
146+     tryFlushBatch ( ) ; 
147+   } ,  [ ] ) ; 
148+ 
149+   // Task list 
150+ 
151+   const  batchUpdate : BatchTask  =  ( key ,  callback )  =>  { 
152+     batchUpdateTasksRef . current . push ( [ key ,  callback ] ) ; 
153+     tryFlushBatch ( ) ; 
154+   } ; 
155+ 
156+   setBatchUpdate ( batchUpdate ) ; 
157+ 
158+   // ========================== Unmount =========================== 
121159  React . useEffect ( 
122160    ( )  =>  ( )  =>  destroyForm ( clearOnDestroy ) , 
123161    // eslint-disable-next-line react-hooks/exhaustive-deps 
@@ -146,6 +184,7 @@ const Form: React.ForwardRefRenderFunction<FormRef, FormProps> = (
146184    prevFieldsRef . current  =  fields ; 
147185  } ,  [ fields ,  formInstance ] ) ; 
148186
187+   // =========================== Render =========================== 
149188  const  formContextValue  =  React . useMemo ( 
150189    ( )  =>  ( { 
151190      ...( formInstance  as  InternalFormInstance ) , 
@@ -157,6 +196,7 @@ const Form: React.ForwardRefRenderFunction<FormRef, FormProps> = (
157196  const  wrapperNode  =  ( 
158197    < ListContext . Provider  value = { null } > 
159198      < FieldContext . Provider  value = { formContextValue } > { childrenNode } </ FieldContext . Provider > 
199+       < BatchUpdate  ref = { setBatchUpdateRef }  /> 
160200    </ ListContext . Provider > 
161201  ) ; 
162202
0 commit comments