diff --git a/.changeset/nice-papayas-care.md b/.changeset/nice-papayas-care.md new file mode 100644 index 000000000000..6f3a1714742f --- /dev/null +++ b/.changeset/nice-papayas-care.md @@ -0,0 +1,11 @@ +--- +"@refinedev/core": patch +--- + +fix: use stable array to prevent memoization issue in useList. #7019 + +Fixed an issue where `useList`, `useMany`, `useTable`, and `useCustom` hooks created new empty arrays/objects on every render. This caused `useEffect` and `useMemo` to trigger unnecessarily. + +Now these hooks use stable references for better performance. + +Fixes #7019 diff --git a/packages/core/src/hooks/data/useCustom.ts b/packages/core/src/hooks/data/useCustom.ts index 65056143c3e3..1c0299bbe38f 100644 --- a/packages/core/src/hooks/data/useCustom.ts +++ b/packages/core/src/hooks/data/useCustom.ts @@ -114,6 +114,8 @@ export type UseCustomReturnType = { }; } & UseLoadingOvertimeReturnType; +const EMPTY_OBJECT = Object.freeze({}) as any; + export const useCustom = < TQueryFnData extends BaseRecord = BaseRecord, TError extends HttpError = HttpError, @@ -231,7 +233,7 @@ export const useCustom = < return { query: queryResponse, result: { - data: queryResponse.data?.data || ({} as TData), + data: queryResponse.data?.data || EMPTY_OBJECT, }, overtime: { elapsedTime }, }; diff --git a/packages/core/src/hooks/data/useList.ts b/packages/core/src/hooks/data/useList.ts index ad981ae445f6..ee471493e653 100644 --- a/packages/core/src/hooks/data/useList.ts +++ b/packages/core/src/hooks/data/useList.ts @@ -101,6 +101,8 @@ export type UseListReturnType = { }; } & UseLoadingOvertimeReturnType; +const EMPTY_ARRAY = Object.freeze([]) as []; + /** * `useList` is a modified version of `react-query`'s {@link https://tanstack.com/query/v5/docs/framework/react/guides/queries `useQuery`} used for retrieving items from a `resource` with pagination, sort, and filter configurations. * @@ -315,7 +317,7 @@ export const useList = < return { query: queryResponse, result: { - data: queryResponse?.data?.data || [], + data: queryResponse?.data?.data || EMPTY_ARRAY, total: queryResponse?.data?.total, }, overtime: { elapsedTime }, diff --git a/packages/core/src/hooks/data/useMany.ts b/packages/core/src/hooks/data/useMany.ts index 8d2b1f3d6fba..ed67473f4a08 100644 --- a/packages/core/src/hooks/data/useMany.ts +++ b/packages/core/src/hooks/data/useMany.ts @@ -85,6 +85,8 @@ export type UseManyProps = { LiveModeProps & UseLoadingOvertimeOptionsProps; +const EMPTY_ARRAY = Object.freeze([]) as []; + /** * `useMany` is a modified version of `react-query`'s {@link https://tanstack.com/query/v5/docs/framework/react/guides/queries `useQuery`} used for retrieving multiple items from a `resource`. * @@ -259,7 +261,7 @@ export const useMany = < return { query: queryResponse, result: { - data: queryResponse?.data?.data || [], + data: queryResponse?.data?.data || EMPTY_ARRAY, }, overtime: { elapsedTime }, }; diff --git a/packages/core/src/hooks/useTable/index.ts b/packages/core/src/hooks/useTable/index.ts index 85641c11973f..8765d1dea7f3 100644 --- a/packages/core/src/hooks/useTable/index.ts +++ b/packages/core/src/hooks/useTable/index.ts @@ -176,6 +176,7 @@ export type useTableReturnType< const defaultPermanentFilter: CrudFilter[] = []; const defaultPermanentSorter: CrudSort[] = []; +const EMPTY_ARRAY = Object.freeze([]) as []; export function useTable< TQueryFnData extends BaseRecord = BaseRecord, @@ -434,7 +435,7 @@ export function useTable< createLinkForSyncWithLocation, overtime: queryResult.overtime, result: { - data: queryResult.result?.data || [], + data: queryResult.result?.data || EMPTY_ARRAY, total: queryResult.result?.total, }, };