Skip to content

Commit 58e3b66

Browse files
fix: performance optimization
1 parent 7a20af0 commit 58e3b66

File tree

1 file changed

+31
-7
lines changed

1 file changed

+31
-7
lines changed

src/useFormState.ts

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,6 @@ type FormIndexKeyMap = Record<number, IndexKeyMap>;
126126
export type FormRefKeyMap = Record<number, RefKeyMap>;
127127

128128
export function useInnerContext(skip?: boolean) {
129-
// const formIndex = React.useRef<number>(0);
130129
const [lastKey, setLastKey] = useRefState<string | undefined>(undefined);
131130
const refIndex = React.useRef<number>(0);
132131

@@ -305,20 +304,43 @@ export default function useFormState<T>(
305304
const [wasSubmitted, setWasSubmitted] = useRefState<boolean>(false);
306305
const [touched, sTouched] = useRefState<BooleanUtility<T>>({});
307306
const [focusedOnce, sFocusedOnce] = useRefState<BooleanUtility<T>>({});
307+
const initialErrorCache = React.useRef<ErrorUtility<T>>({});
308308
const [errors, sErrors] = useRefState<ErrorUtility<T>>({});
309309
const [values, setValues] = useRefState<T>(initialState);
310310
const [lastCharacters, setLastCharacters] = useRefState<
311311
FieldsLastCharacters<T>
312312
>({});
313313

314+
React.useEffect(() => {
315+
// render optimization because we don't want to re-render on every field at the beginning of the onLayout calls :)
316+
const timer = setTimeout(() => {
317+
sErrors(initialErrorCache.current);
318+
}, 100);
319+
return () => {
320+
clearTimeout(timer);
321+
};
322+
}, [initialErrorCache, sErrors]);
323+
314324
const setError = React.useCallback(
315-
<K extends DotNestedKeys<T>>(k: K, v: boolean | string | undefined) => {
325+
<K extends DotNestedKeys<T>>(
326+
k: K,
327+
v: boolean | string | undefined,
328+
initial?: boolean
329+
) => {
316330
const error = deepGet(errors.current, k);
317331
if (v !== error) {
318-
sErrors((prev) => deepSet(prev, k, v) as any);
332+
if (initial) {
333+
initialErrorCache.current = deepSet(
334+
initialErrorCache.current || {},
335+
k,
336+
v
337+
) as any;
338+
} else {
339+
sErrors((prev) => deepSet(prev, k, v) as any);
340+
}
319341
}
320342
},
321-
[errors, sErrors]
343+
[errors, sErrors, initialErrorCache]
322344
);
323345

324346
const clearErrors = React.useCallback(() => {
@@ -330,7 +352,8 @@ export default function useFormState<T>(
330352
k: K,
331353
h: Customizing<T, K> | CustomizingRaw<T, K> | undefined,
332354
v: GetFieldType<T, K>,
333-
allV: T
355+
allV: T,
356+
initial?: boolean
334357
) => {
335358
let err: boolean | string | undefined;
336359

@@ -348,7 +371,8 @@ export default function useFormState<T>(
348371
}
349372
setError(
350373
k,
351-
err === true || err === undefined || err === null ? false : err
374+
err === true || err === undefined || err === null ? false : err,
375+
initial
352376
);
353377
},
354378
[setError]
@@ -440,7 +464,7 @@ export default function useFormState<T>(
440464
referencedCallback(`layout.${k}`, (e: LayoutChangeEvent) => {
441465
h?.onLayout?.(e);
442466
const value = deepGet(values.current, k);
443-
checkError(k as DotNestedKeys<T>, h, value as any, values.current);
467+
checkError(k as DotNestedKeys<T>, h, value as any, values.current, true);
444468
});
445469

446470
const text = <K extends DotNestedKeys<T>>(

0 commit comments

Comments
 (0)