From 9198d6b32d023b37fea31a3ce042de75d745ede5 Mon Sep 17 00:00:00 2001 From: Avram Walden Date: Thu, 1 Feb 2024 13:43:58 -0800 Subject: [PATCH] =?UTF-8?q?fix:=20=F0=9F=90=9B=20Remove=20memoization=20of?= =?UTF-8?q?=20returned=20methods?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 🎸 Removes memoization of returned methods * test: 💍 console log * chore: 🤖 adds dist folder to gitignore * fix: 🐛 replaces useEffect/useRef pattern with useMemo --- .gitignore | 3 + src/useInertiaForm.ts | 241 +++++++++++++++++++++--------------------- 2 files changed, 122 insertions(+), 122 deletions(-) diff --git a/.gitignore b/.gitignore index 8f32b38..90f31a3 100644 --- a/.gitignore +++ b/.gitignore @@ -117,3 +117,6 @@ typings/ # dotenv environment variables file .env .env.* + +# compiled files +dist/ \ No newline at end of file diff --git a/src/useInertiaForm.ts b/src/useInertiaForm.ts index edb15b3..9109530 100644 --- a/src/useInertiaForm.ts +++ b/src/useInertiaForm.ts @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useRef, useState } from 'react' +import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { Method, Progress, VisitOptions, type RequestPayload } from '@inertiajs/core' import { router } from '@inertiajs/react' import { get, isEqual, set } from 'lodash' @@ -102,12 +102,12 @@ export default function useInertiaForm( const [data, setData] = rememberKey ? useRemember(transformedData, `${rememberKey}:data`) : useState(transformedData) // Detect root model name - const rootModelRef = useRef() - useEffect(() => { + const rootModelKey = useMemo(() => { const keys = data ? Object.keys(data) : [] if(keys.length === 1) { - rootModelRef.current = keys[0] + return keys[0] } + return undefined }, []) // Errors @@ -118,11 +118,11 @@ export default function useInertiaForm( // Use to prepend root model name to errors returned by the server const rewriteErrorKeys = (errors: Partial>) => { - if(!errors || !rootModelRef.current) return errors + if(!errors || !rootModelKey) return errors const newErrors = {} Object.keys(errors).forEach(key => { - newErrors[`${rootModelRef.current}.${key}`] = errors[key] + newErrors[`${rootModelKey}.${key}`] = errors[key] }) return newErrors } @@ -162,110 +162,107 @@ export default function useInertiaForm( railsAttributes = meta.railsAttributes } catch(e) {} - const submit = useCallback( - (method: Method, url: string, options: VisitOptions = {}) => { - const _options = { - ...options, - onCancelToken: (token) => { - cancelToken.current = token + const submit = (method: Method, url: string, options: VisitOptions = {}) => { + const _options = { + ...options, + onCancelToken: (token) => { + cancelToken.current = token - if(options.onCancelToken) { - return options.onCancelToken(token) - } - }, - onBefore: (visit) => { - setWasSuccessful(false) - setRecentlySuccessful(false) - clearTimeout(recentlySuccessfulTimeoutId.current) - - if(options.onBefore) { - return options.onBefore(visit) - } - }, - onStart: (visit) => { - setProcessing(true) + if(options.onCancelToken) { + return options.onCancelToken(token) + } + }, + onBefore: (visit) => { + setWasSuccessful(false) + setRecentlySuccessful(false) + clearTimeout(recentlySuccessfulTimeoutId.current) + + if(options.onBefore) { + return options.onBefore(visit) + } + }, + onStart: (visit) => { + setProcessing(true) - if(options.onStart) { - return options.onStart(visit) - } - }, - onProgress: (event) => { - setProgress(event) + if(options.onStart) { + return options.onStart(visit) + } + }, + onProgress: (event) => { + setProgress(event) - if(options.onProgress) { - return options.onProgress(event) - } - }, - onSuccess: (page) => { - if(isMounted.current) { - setProcessing(false) - setProgress(null) - setErrors({}) - setHasErrors(false) - setWasSuccessful(true) - setRecentlySuccessful(true) - recentlySuccessfulTimeoutId.current = setTimeout(() => { - if(isMounted.current) { - setRecentlySuccessful(false) - } - }, 2000) - } + if(options.onProgress) { + return options.onProgress(event) + } + }, + onSuccess: (page) => { + if(isMounted.current) { + setProcessing(false) + setProgress(null) + setErrors({}) + setHasErrors(false) + setWasSuccessful(true) + setRecentlySuccessful(true) + recentlySuccessfulTimeoutId.current = setTimeout(() => { + if(isMounted.current) { + setRecentlySuccessful(false) + } + }, 2000) + } - if(options.onSuccess) { - return options.onSuccess(page) - } - }, - onError: (errors) => { - if(isMounted.current) { - setProcessing(false) - setProgress(null) - setErrors(rewriteErrorKeys(errors)) - setHasErrors(true) - } + if(options.onSuccess) { + return options.onSuccess(page) + } + }, + onError: (errors) => { + if(isMounted.current) { + setProcessing(false) + setProgress(null) + setErrors(rewriteErrorKeys(errors)) + setHasErrors(true) + } - if(options.onError) { - return options.onError(errors) - } - }, - onCancel: () => { - if(isMounted.current) { - setProcessing(false) - setProgress(null) - } + if(options.onError) { + return options.onError(errors) + } + }, + onCancel: () => { + if(isMounted.current) { + setProcessing(false) + setProgress(null) + } - if(options.onCancel) { - return options.onCancel() - } - }, - onFinish: (visit) => { - if(isMounted.current) { - setProcessing(false) - setProgress(null) - } + if(options.onCancel) { + return options.onCancel() + } + }, + onFinish: (visit) => { + if(isMounted.current) { + setProcessing(false) + setProgress(null) + } - cancelToken.current = null + cancelToken.current = null - if(options.onFinish) { - return options.onFinish(visit) - } - }, - } + if(options.onFinish) { + return options.onFinish(visit) + } + }, + } - let transformedData = transformRef.current(structuredClone(data)) - if(railsAttributes) { - transformedData = renameObjectWithAttributes(transformedData) - } + let transformedData = transformRef.current(structuredClone(data)) + if(railsAttributes) { + transformedData = renameObjectWithAttributes(transformedData) + } - if(method === 'delete') { - router.delete(url, { ..._options, data: transformedData as RequestPayload }) - } else { - router[method](url, transformedData as RequestPayload, _options) - } - }, - [data, setErrors], - ) + if(method === 'delete') { + router.delete(url, { ..._options, data: transformedData as RequestPayload }) + } else { + router[method](url, transformedData as RequestPayload, _options) + } + } - const clearErrors = useCallback((fields?: string|string[]|Path|Path[]) => { + const clearErrors = (fields?: string|string[]|Path|Path[]) => { if(!fields) { setErrors({}) return @@ -284,7 +281,7 @@ export default function useInertiaForm( setHasErrors(Object.keys(newErrors).length > 0) return newErrors }) - }, [errors]) + } return { data, @@ -339,7 +336,7 @@ export default function useInertiaForm( return get(data, key) }, - unsetData: useCallback((key: string) => { + unsetData: (key: string) => { setData(data => { const clone = structuredClone(data) if(onChangeRef.current) { @@ -348,9 +345,9 @@ export default function useInertiaForm( unsetCompact(clone as NestedObject, key) return clone }) - }, [data]), + }, - setDefaults: useCallback((fieldOrFields?: string|TForm, maybeValue?: string) => { + setDefaults: (fieldOrFields?: string|TForm, maybeValue?: string) => { if(fieldOrFields === undefined) { setDefaults(() => data) return @@ -360,9 +357,9 @@ export default function useInertiaForm( ...defaults, ...(typeof fieldOrFields === 'string' ? { [fieldOrFields]: maybeValue } : (fieldOrFields as TForm)), })) - }, [data]), + }, - reset: useCallback((fields?: string|string[]) => { + reset: (fields?: string|string[]) => { if(!fields) { if(onChangeRef.current) { onChangeArgsRef.current = [undefined, defaults, data] @@ -383,9 +380,9 @@ export default function useInertiaForm( onChangeArgsRef.current = [undefined, clone, data] } setData(clone) - }, [defaults, data]), + }, - setError: useCallback((fieldOrFields: string|Record, maybeValue?: string) => { + setError: (fieldOrFields: string|Record, maybeValue?: string) => { setErrors((errors) => { const newErrors = { ...errors, @@ -396,40 +393,40 @@ export default function useInertiaForm( setHasErrors(Object.keys(newErrors).length > 0) return newErrors }) - }, [errors]), + }, - getError: useCallback((key: string): string|string[] => { + getError: (key: string): string|string[] => { return get(errors, key) - }, [errors]), + }, clearErrors, submit, - get: useCallback((url, options) => { + get: (url, options) => { submit('get', url, options) - }, []), + }, - post: useCallback((url, options) => { + post: (url, options) => { submit('post', url, options) - }, []), + }, - put: useCallback((url, options) => { + put: (url, options) => { submit('put', url, options) - }, []), + }, - patch: useCallback((url, options) => { + patch: (url, options) => { submit('patch', url, options) - }, []), + }, - delete: useCallback((url, options) => { + delete: (url, options) => { submit('delete', url, options) - }, []), + }, - cancel: useCallback(() => { + cancel: () => { if(cancelToken.current) { cancelToken.current.cancel() } - }, [cancelToken.current]), + }, } }