refactor: use hook for fetch event

This commit is contained in:
jialin
2026-06-16 22:28:46 +08:00
committed by jialin
parent 737d43fd16
commit cdd6ef9cb3
2 changed files with 59 additions and 39 deletions
+29 -39
View File
@@ -9,23 +9,15 @@
* event-type selects ride in the bar's ``extra`` slot. * event-type selects ride in the bar's ``extra`` slot.
*/ */
import { useAccess, useIntl } from '@umijs/max'; import { useAccess, useIntl } from '@umijs/max';
import { useMemoizedFn } from 'ahooks';
import { Input, Select, Table, Tag } from 'antd'; import { Input, Select, Table, Tag } from 'antd';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import _ from 'lodash'; import _ from 'lodash';
import React, { import React, { useEffect, useMemo, useRef, useState } from 'react';
useCallback, import { ResourceEventItem } from '../apis/resource';
useEffect,
useMemo,
useRef,
useState
} from 'react';
import {
queryResourceEvents,
ResourceEventItem,
ResourceEventsResponse
} from '../apis/resource';
import ResourceFilterBar from '../components/resource-filter-bar'; import ResourceFilterBar from '../components/resource-filter-bar';
import { parseRollup } from '../utils/time-buckets'; import { parseRollup } from '../utils/time-buckets';
import useQueryResourceEvents from './services/use-query-resource-events';
// Only these four are ever emitted (see resource_event_logger): create/delete // Only these four are ever emitted (see resource_event_logger): create/delete
// + the metering-window pair. updated/attached/detached exist as enum values // + the metering-window pair. updated/attached/detached exist as enum values
@@ -115,15 +107,17 @@ const ResourceEvents: React.FC = () => {
eventTypes: string[]; eventTypes: string[];
nameQuery: string; nameQuery: string;
page: number; page: number;
perPage: number;
}; };
const [queryParams, setQueryParams] = useState<QueryParams>({ const [queryParams, setQueryParams] = useState<QueryParams>({
dateRange: [dayjs().subtract(29, 'day'), dayjs()], dateRange: [dayjs().subtract(29, 'day'), dayjs()],
resourceType: undefined, resourceType: undefined,
eventTypes: [], eventTypes: [],
nameQuery: '', nameQuery: '',
perPage: 50,
page: 1 page: 1
}); });
const [data, setData] = useState<ResourceEventsResponse | null>(null); const { detailData: data, loading, fetchData } = useQueryResourceEvents();
// Latest params, so the stable debounced name handler reads current values. // Latest params, so the stable debounced name handler reads current values.
const queryRef = useRef(queryParams); const queryRef = useRef(queryParams);
@@ -132,30 +126,20 @@ const ResourceEvents: React.FC = () => {
// Single fetch entry point: merge the patch into the current params, persist // Single fetch entry point: merge the patch into the current params, persist
// them, then request — triggered from each handler rather than from effect // them, then request — triggered from each handler rather than from effect
// dependencies, so there's exactly one request per user action. // dependencies, so there's exactly one request per user action.
const fetchEvents = useCallback( const fetchEvents = useMemoizedFn((patch: Partial<QueryParams>) => {
async (patch: Partial<QueryParams>) => { const params = { ...queryRef.current, ...patch };
const params = { ...queryRef.current, ...patch }; setQueryParams(params);
setQueryParams(params); return fetchData({
try { start_date: params.dateRange[0].format('YYYY-MM-DD'),
const res = await queryResourceEvents({ end_date: params.dateRange[1].format('YYYY-MM-DD'),
start_date: params.dateRange[0].format('YYYY-MM-DD'), scope,
end_date: params.dateRange[1].format('YYYY-MM-DD'), resource_types: params.resourceType ? [params.resourceType] : undefined,
scope, resource_name: params.nameQuery || undefined,
resource_types: params.resourceType event_types: params.eventTypes,
? [params.resourceType] page: params.page,
: undefined, perPage: 50
resource_name: params.nameQuery || undefined, });
event_types: params.eventTypes, });
page: params.page,
perPage: 50
});
setData(res);
} catch {
// Keep last response on failure.
}
},
[scope]
);
// First load only — subsequent fetches are driven by the handlers below. // First load only — subsequent fetches are driven by the handlers below.
useEffect(() => { useEffect(() => {
@@ -278,11 +262,17 @@ const ResourceEvents: React.FC = () => {
dataSource={data?.items ?? []} dataSource={data?.items ?? []}
columns={columns as any} columns={columns as any}
style={{ marginTop: 24 }} style={{ marginTop: 24 }}
loading={{
spinning: loading,
size: 'middle'
}}
pagination={{ pagination={{
size: 'middle', size: 'middle',
current: queryParams.page, current: queryParams.page,
pageSize: data?.pagination.perPage ?? 50, pageSize: data?.pagination?.perPage ?? 50,
total: data?.pagination.total ?? 0, total: data?.pagination?.total ?? 0,
showSizeChanger: false,
hideOnSinglePage: queryParams.perPage === 50,
onChange: (p) => fetchEvents({ page: p }) onChange: (p) => fetchEvents({ page: p })
}} }}
/> />
@@ -0,0 +1,30 @@
import { useQueryData } from '@/hooks/use-query-data-list';
import {
queryResourceEvents,
ResourceEventsResponse
} from '../../apis/resource';
type ResourceEventsParams = Parameters<typeof queryResourceEvents>[0];
/**
* Wraps the `queryResourceEvents` request with shared loading state and
* in-flight cancellation (the previous request is cancelled on each new fetch
* and on unmount), so rapid filter/name-search/page changes can't race a stale
* response onto the table.
*/
export default function useQueryResourceEvents(option?: { key?: string }) {
const { detailData, loading, cancelRequest, fetchData } = useQueryData<
ResourceEventsResponse,
ResourceEventsParams
>({
fetchDetail: queryResourceEvents,
key: option?.key || 'resourceEvents'
});
return {
detailData,
loading,
cancelRequest,
fetchData
};
}