From f83bd778c1b20f049fd63edf2ebc4bd8391c281c Mon Sep 17 00:00:00 2001 From: Hasan Mir Date: Mon, 10 Jul 2023 10:11:40 +0330 Subject: [PATCH 1/3] fix react's useForm hook that returns new references for functions like setData, clearErrors, etc on every re-render --- packages/react/src/useForm.ts | 102 ++++++++++++++++++++++------------ 1 file changed, 65 insertions(+), 37 deletions(-) diff --git a/packages/react/src/useForm.ts b/packages/react/src/useForm.ts index c36a2f054..f3fdbc270 100644 --- a/packages/react/src/useForm.ts +++ b/packages/react/src/useForm.ts @@ -165,9 +165,8 @@ export default function useForm>( [data, setErrors], ) - return { - data, - setData(keyOrData: keyof TForm | Function | TForm, maybeValue?: TForm[keyof TForm]) { + const setDataFunction = useCallback( + (keyOrData: keyof TForm | Function | TForm, maybeValue?: TForm[keyof TForm]) => { if (typeof keyOrData === 'string') { setData({ ...data, [keyOrData]: maybeValue }) } else if (typeof keyOrData === 'function') { @@ -176,17 +175,11 @@ export default function useForm>( setData(keyOrData as TForm) } }, - isDirty: !isEqual(data, defaults), - errors, - hasErrors, - processing, - progress, - wasSuccessful, - recentlySuccessful, - transform(callback) { - transform = callback - }, - setDefaults(fieldOrFields?: keyof TForm | Record, maybeValue?: string) { + [data, setData], + ) + + const setDefaultsFunction = useCallback( + (fieldOrFields?: keyof TForm | Record, maybeValue?: string) => { if (typeof fieldOrFields === 'undefined') { setDefaults(() => data) } else { @@ -196,7 +189,11 @@ export default function useForm>( })) } }, - reset(...fields) { + [data, setDefaults], + ) + + const reset = useCallback( + (...fields) => { if (fields.length === 0) { setData(defaults) } else { @@ -213,7 +210,11 @@ export default function useForm>( ) } }, - setError(fieldOrFields: keyof TForm | Record, maybeValue?: string) { + [data, setData, defaults], + ) + + const setError = useCallback( + (fieldOrFields: keyof TForm | Record, maybeValue?: string) => { setErrors((errors) => { const newErrors = { ...errors, @@ -225,7 +226,11 @@ export default function useForm>( return newErrors }) }, - clearErrors(...fields) { + [setErrors, setHasErrors], + ) + + const clearErrors = useCallback( + (...fields) => { setErrors((errors) => { const newErrors = (Object.keys(errors) as Array).reduce( (carry, field) => ({ @@ -238,26 +243,49 @@ export default function useForm>( return newErrors }) }, + [setErrors, setHasErrors], + ) + + const createSubmitMethod = (method) => (url, options) => { + submit(method, url, options) + } + const get = useCallback(createSubmitMethod('get'), [submit]) + const post = useCallback(createSubmitMethod('post'), [submit]) + const put = useCallback(createSubmitMethod('put'), [submit]) + const patch = useCallback(createSubmitMethod('patch'), [submit]) + const deleteMethod = useCallback(createSubmitMethod('delete'), [submit]) + + const cancel = useCallback(() => { + if (cancelToken.current) { + cancelToken.current.cancel() + } + }, []) + + const transformFunction = useCallback((callback) => { + transform = callback + }, []) + + return { + data, + setData: setDataFunction, + isDirty: !isEqual(data, defaults), + errors, + hasErrors, + processing, + progress, + wasSuccessful, + recentlySuccessful, + transform: transformFunction, + setDefaults: setDefaultsFunction, + reset, + setError, + clearErrors, submit, - get(url, options) { - submit('get', url, options) - }, - post(url, options) { - submit('post', url, options) - }, - put(url, options) { - submit('put', url, options) - }, - patch(url, options) { - submit('patch', url, options) - }, - delete(url, options) { - submit('delete', url, options) - }, - cancel() { - if (cancelToken.current) { - cancelToken.current.cancel() - } - }, + get, + post, + put, + patch, + delete: deleteMethod, + cancel, } } From b99dffc98aa8985ebf2432ee2a94b3532e692cc1 Mon Sep 17 00:00:00 2001 From: Hasan Mir Date: Mon, 10 Jul 2023 10:45:48 +0330 Subject: [PATCH 2/3] fix setData and reset methods --- packages/react/src/useForm.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/react/src/useForm.ts b/packages/react/src/useForm.ts index f3fdbc270..bfc7212b8 100644 --- a/packages/react/src/useForm.ts +++ b/packages/react/src/useForm.ts @@ -168,14 +168,14 @@ export default function useForm>( const setDataFunction = useCallback( (keyOrData: keyof TForm | Function | TForm, maybeValue?: TForm[keyof TForm]) => { if (typeof keyOrData === 'string') { - setData({ ...data, [keyOrData]: maybeValue }) + setData((data) => ({ ...data, [keyOrData]: maybeValue })) } else if (typeof keyOrData === 'function') { setData((data) => keyOrData(data)) } else { setData(keyOrData as TForm) } }, - [data, setData], + [setData], ) const setDefaultsFunction = useCallback( @@ -197,7 +197,7 @@ export default function useForm>( if (fields.length === 0) { setData(defaults) } else { - setData( + setData((data) => (Object.keys(defaults) as Array) .filter((key) => fields.includes(key)) .reduce( @@ -210,7 +210,7 @@ export default function useForm>( ) } }, - [data, setData, defaults], + [setData, defaults], ) const setError = useCallback( From b24ca1ced1b638e7b40aee1aa08cd539b350eba7 Mon Sep 17 00:00:00 2001 From: Hasan Mir Date: Mon, 7 Aug 2023 15:45:48 +0330 Subject: [PATCH 3/3] Fix the transform function's bug --- packages/react/src/useForm.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/react/src/useForm.ts b/packages/react/src/useForm.ts index bfc7212b8..b1e0f9da0 100644 --- a/packages/react/src/useForm.ts +++ b/packages/react/src/useForm.ts @@ -58,7 +58,7 @@ export default function useForm>( const [progress, setProgress] = useState(null) const [wasSuccessful, setWasSuccessful] = useState(false) const [recentlySuccessful, setRecentlySuccessful] = useState(false) - let transform = (data) => data + const transform = useRef((data) => data) useEffect(() => { isMounted.current = true @@ -157,9 +157,9 @@ export default function useForm>( } if (method === 'delete') { - router.delete(url, { ..._options, data: transform(data) }) + router.delete(url, { ..._options, data: transform.current(data) }) } else { - router[method](url, transform(data), _options) + router[method](url, transform.current(data), _options) } }, [data, setErrors], @@ -262,7 +262,7 @@ export default function useForm>( }, []) const transformFunction = useCallback((callback) => { - transform = callback + transform.current = callback }, []) return {