fix(usage): memoize resource breakdown filters (review comment)
The GPU Instances / Storage tabs built the filter object inline (in baseRequest and again in the extra tab's props), duplicating the conditional-spread logic and handing the enterprise Organization tab a fresh object every render — which refired its fetch effect on any state change. Hoist it into one memoized ``breakdownFilters`` shared by the chart request and the extra tab, mirroring the Tokens tab's stable-filters shape.
This commit is contained in:
@@ -164,29 +164,37 @@ const GpuInstancesTab: React.FC = () => {
|
|||||||
fetchData: fetchChartData
|
fetchData: fetchChartData
|
||||||
} = useQueryGpuInstancesBreakdown({ key: 'gpuInstancesBreakdownChart' });
|
} = useQueryGpuInstancesBreakdown({ key: 'gpuInstancesBreakdownChart' });
|
||||||
|
|
||||||
|
// Single source of truth for the active filter set — memoized so its
|
||||||
|
// reference only changes when a selection changes (an inline object would
|
||||||
|
// refire the extra tab's fetch effect on every render), and shared by both
|
||||||
|
// the chart request and the enterprise extra tab (no duplicated spread).
|
||||||
|
const breakdownFilters = useMemo(
|
||||||
|
() => ({
|
||||||
|
...(selectedUsers.length ? { creator_ids: selectedUsers } : {}),
|
||||||
|
...(selectedInstances.length ? { instance_ids: selectedInstances } : {}),
|
||||||
|
...(selectedOrganizations.length
|
||||||
|
? { organization_ids: selectedOrganizations }
|
||||||
|
: {}),
|
||||||
|
...(selectedUserGroups.length
|
||||||
|
? { user_group_ids: selectedUserGroups }
|
||||||
|
: {})
|
||||||
|
}),
|
||||||
|
[
|
||||||
|
selectedUsers,
|
||||||
|
selectedInstances,
|
||||||
|
selectedOrganizations,
|
||||||
|
selectedUserGroups
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
const baseRequest = (): Omit<ResourceBreakdownRequest, 'group_by'> => ({
|
const baseRequest = (): Omit<ResourceBreakdownRequest, 'group_by'> => ({
|
||||||
start_date: dateRange[0].format('YYYY-MM-DD'),
|
start_date: dateRange[0].format('YYYY-MM-DD'),
|
||||||
end_date: dateRange[1].format('YYYY-MM-DD'),
|
end_date: dateRange[1].format('YYYY-MM-DD'),
|
||||||
scope,
|
scope,
|
||||||
granularity,
|
granularity,
|
||||||
filters:
|
filters: Object.keys(breakdownFilters).length
|
||||||
selectedUsers.length ||
|
? breakdownFilters
|
||||||
selectedInstances.length ||
|
: undefined,
|
||||||
selectedOrganizations.length ||
|
|
||||||
selectedUserGroups.length
|
|
||||||
? {
|
|
||||||
...(selectedUsers.length ? { creator_ids: selectedUsers } : {}),
|
|
||||||
...(selectedInstances.length
|
|
||||||
? { instance_ids: selectedInstances }
|
|
||||||
: {}),
|
|
||||||
...(selectedOrganizations.length
|
|
||||||
? { organization_ids: selectedOrganizations }
|
|
||||||
: {}),
|
|
||||||
...(selectedUserGroups.length
|
|
||||||
? { user_group_ids: selectedUserGroups }
|
|
||||||
: {})
|
|
||||||
}
|
|
||||||
: undefined,
|
|
||||||
page: 1,
|
page: 1,
|
||||||
perPage: 50
|
perPage: 50
|
||||||
});
|
});
|
||||||
@@ -536,20 +544,7 @@ const GpuInstancesTab: React.FC = () => {
|
|||||||
tab="gpu-instances"
|
tab="gpu-instances"
|
||||||
dateRange={dateRange}
|
dateRange={dateRange}
|
||||||
scope={scope}
|
scope={scope}
|
||||||
filters={{
|
filters={breakdownFilters}
|
||||||
...(selectedUsers.length
|
|
||||||
? { creator_ids: selectedUsers }
|
|
||||||
: {}),
|
|
||||||
...(selectedInstances.length
|
|
||||||
? { instance_ids: selectedInstances }
|
|
||||||
: {}),
|
|
||||||
...(selectedOrganizations.length
|
|
||||||
? { organization_ids: selectedOrganizations }
|
|
||||||
: {}),
|
|
||||||
...(selectedUserGroups.length
|
|
||||||
? { user_group_ids: selectedUserGroups }
|
|
||||||
: {})
|
|
||||||
}}
|
|
||||||
pageResetKey={pageResetKey}
|
pageResetKey={pageResetKey}
|
||||||
refreshKey={refreshKey}
|
refreshKey={refreshKey}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -158,27 +158,32 @@ const StorageTab: React.FC = () => {
|
|||||||
fetchData: fetchChartData
|
fetchData: fetchChartData
|
||||||
} = useQueryStorageBreakdown({ key: 'storageBreakdownChart' });
|
} = useQueryStorageBreakdown({ key: 'storageBreakdownChart' });
|
||||||
|
|
||||||
|
// Single source of truth for the active filter set — memoized so its
|
||||||
|
// reference only changes when a selection changes (an inline object would
|
||||||
|
// refire the extra tab's fetch effect on every render), and shared by both
|
||||||
|
// the chart request and the enterprise extra tab (no duplicated spread).
|
||||||
|
const breakdownFilters = useMemo(
|
||||||
|
() => ({
|
||||||
|
...(selectedUsers.length ? { creator_ids: selectedUsers } : {}),
|
||||||
|
...(selectedVolumes.length ? { volume_ids: selectedVolumes } : {}),
|
||||||
|
...(selectedOrganizations.length
|
||||||
|
? { organization_ids: selectedOrganizations }
|
||||||
|
: {}),
|
||||||
|
...(selectedUserGroups.length
|
||||||
|
? { user_group_ids: selectedUserGroups }
|
||||||
|
: {})
|
||||||
|
}),
|
||||||
|
[selectedUsers, selectedVolumes, selectedOrganizations, selectedUserGroups]
|
||||||
|
);
|
||||||
|
|
||||||
const baseRequest = (): Omit<ResourceBreakdownRequest, 'group_by'> => ({
|
const baseRequest = (): Omit<ResourceBreakdownRequest, 'group_by'> => ({
|
||||||
start_date: dateRange[0].format('YYYY-MM-DD'),
|
start_date: dateRange[0].format('YYYY-MM-DD'),
|
||||||
end_date: dateRange[1].format('YYYY-MM-DD'),
|
end_date: dateRange[1].format('YYYY-MM-DD'),
|
||||||
scope,
|
scope,
|
||||||
granularity,
|
granularity,
|
||||||
filters:
|
filters: Object.keys(breakdownFilters).length
|
||||||
selectedUsers.length ||
|
? breakdownFilters
|
||||||
selectedVolumes.length ||
|
: undefined,
|
||||||
selectedOrganizations.length ||
|
|
||||||
selectedUserGroups.length
|
|
||||||
? {
|
|
||||||
...(selectedUsers.length ? { creator_ids: selectedUsers } : {}),
|
|
||||||
...(selectedVolumes.length ? { volume_ids: selectedVolumes } : {}),
|
|
||||||
...(selectedOrganizations.length
|
|
||||||
? { organization_ids: selectedOrganizations }
|
|
||||||
: {}),
|
|
||||||
...(selectedUserGroups.length
|
|
||||||
? { user_group_ids: selectedUserGroups }
|
|
||||||
: {})
|
|
||||||
}
|
|
||||||
: undefined,
|
|
||||||
page: 1,
|
page: 1,
|
||||||
perPage: 50
|
perPage: 50
|
||||||
});
|
});
|
||||||
@@ -516,20 +521,7 @@ const StorageTab: React.FC = () => {
|
|||||||
tab="storage"
|
tab="storage"
|
||||||
dateRange={dateRange}
|
dateRange={dateRange}
|
||||||
scope={scope}
|
scope={scope}
|
||||||
filters={{
|
filters={breakdownFilters}
|
||||||
...(selectedUsers.length
|
|
||||||
? { creator_ids: selectedUsers }
|
|
||||||
: {}),
|
|
||||||
...(selectedVolumes.length
|
|
||||||
? { volume_ids: selectedVolumes }
|
|
||||||
: {}),
|
|
||||||
...(selectedOrganizations.length
|
|
||||||
? { organization_ids: selectedOrganizations }
|
|
||||||
: {}),
|
|
||||||
...(selectedUserGroups.length
|
|
||||||
? { user_group_ids: selectedUserGroups }
|
|
||||||
: {})
|
|
||||||
}}
|
|
||||||
pageResetKey={pageResetKey}
|
pageResetKey={pageResetKey}
|
||||||
refreshKey={refreshKey}
|
refreshKey={refreshKey}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user