mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-04 06:58:02 +00:00
refactor(views): use react-query's isLoadingError instead of reimplementing it
deriveQueryStatus previously inferred "never received data" by checking data !== undefined itself. TanStack Query already computes and exposes this exact distinction as isLoadingError (isError && no data) vs isRefetchError (isError && data present) on every useQuery result, so consume that directly instead of duplicating the logic.
This commit is contained in:
@@ -9,12 +9,12 @@ import { deriveQueryStatus } from '../utils/queryUtils';
|
||||
const placeholder: CustomFields = {};
|
||||
|
||||
export default function useCustomFields() {
|
||||
const { data, status, isFetching, isError, refetch } = useQuery({
|
||||
const { data, status, isFetching, isError, isLoadingError, refetch } = useQuery({
|
||||
queryKey: CUSTOM_FIELDS,
|
||||
queryFn: ({ signal }) => getCustomFields({ signal }),
|
||||
placeholderData: (previousData, _previousQuery) => previousData,
|
||||
refetchInterval: queryRefetchIntervalSlow,
|
||||
});
|
||||
|
||||
return { data: data ?? placeholder, status: deriveQueryStatus(status, data), isFetching, isError, refetch };
|
||||
return { data: data ?? placeholder, status: deriveQueryStatus(status, isLoadingError), isFetching, isError, refetch };
|
||||
}
|
||||
|
||||
@@ -7,14 +7,20 @@ import { projectDataPlaceholder } from '../models/ProjectData';
|
||||
import { deriveQueryStatus } from '../utils/queryUtils';
|
||||
|
||||
export default function useProjectData() {
|
||||
const { data, status, isFetching, isError, refetch } = useQuery({
|
||||
const { data, status, isFetching, isError, isLoadingError, refetch } = useQuery({
|
||||
queryKey: PROJECT_DATA,
|
||||
queryFn: ({ signal }) => getProjectData({ signal }),
|
||||
placeholderData: (previousData, _previousQuery) => previousData,
|
||||
refetchInterval: queryRefetchIntervalSlow,
|
||||
});
|
||||
|
||||
return { data: data ?? projectDataPlaceholder, status: deriveQueryStatus(status, data), isFetching, isError, refetch };
|
||||
return {
|
||||
data: data ?? projectDataPlaceholder,
|
||||
status: deriveQueryStatus(status, isLoadingError),
|
||||
isFetching,
|
||||
isError,
|
||||
refetch,
|
||||
};
|
||||
}
|
||||
|
||||
export function useUpdateProjectData() {
|
||||
|
||||
@@ -33,7 +33,7 @@ export default function useRundown() {
|
||||
data: { loaded: loadedRundownId },
|
||||
} = useProjectRundowns();
|
||||
|
||||
const { data, status, isError, refetch, isFetching } = useQuery<Rundown>({
|
||||
const { data, status, isError, isLoadingError, refetch, isFetching } = useQuery<Rundown>({
|
||||
queryKey: loadedRundownId ? getRundownQueryKey(loadedRundownId) : CURRENT_RUNDOWN_QUERY_KEY,
|
||||
queryFn: ({ signal }) => fetchCurrentRundown({ signal }),
|
||||
refetchInterval: queryRefetchIntervalSlow,
|
||||
@@ -51,7 +51,13 @@ export default function useRundown() {
|
||||
queryClient.removeQueries({ queryKey: CURRENT_RUNDOWN_QUERY_KEY, exact: true });
|
||||
}, [loadedRundownId, queryClient]);
|
||||
|
||||
return { data: data ?? cachedRundownPlaceholder, status: deriveQueryStatus(status, data), isError, refetch, isFetching };
|
||||
return {
|
||||
data: data ?? cachedRundownPlaceholder,
|
||||
status: deriveQueryStatus(status, isLoadingError),
|
||||
isError,
|
||||
refetch,
|
||||
isFetching,
|
||||
};
|
||||
}
|
||||
|
||||
export function useRundownWithMetadata() {
|
||||
@@ -128,7 +134,7 @@ export function useRundownAuxData() {
|
||||
export function useRundownById(rundownId: string | null | undefined) {
|
||||
const enabled = Boolean(rundownId);
|
||||
|
||||
const { data, status, isError, refetch, isFetching } = useQuery<Rundown>({
|
||||
const { data, status, isError, isLoadingError, refetch, isFetching } = useQuery<Rundown>({
|
||||
queryKey: getRundownQueryKey(rundownId ?? ''),
|
||||
queryFn: ({ signal }) => fetchRundown(rundownId!, { signal }),
|
||||
enabled,
|
||||
@@ -136,5 +142,11 @@ export function useRundownById(rundownId: string | null | undefined) {
|
||||
refetchInterval: queryRefetchIntervalSlow,
|
||||
});
|
||||
|
||||
return { data: data ?? cachedRundownPlaceholder, status: deriveQueryStatus(status, data), isError, refetch, isFetching };
|
||||
return {
|
||||
data: data ?? cachedRundownPlaceholder,
|
||||
status: deriveQueryStatus(status, isLoadingError),
|
||||
isError,
|
||||
refetch,
|
||||
isFetching,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import { ontimePlaceholderSettings } from '../models/OntimeSettings';
|
||||
import { deriveQueryStatus } from '../utils/queryUtils';
|
||||
|
||||
export default function useSettings() {
|
||||
const { data, status, isFetching, isError, refetch } = useQuery({
|
||||
const { data, status, isFetching, isError, isLoadingError, refetch } = useQuery({
|
||||
queryKey: APP_SETTINGS,
|
||||
queryFn: ({ signal }) => getSettings({ signal }),
|
||||
placeholderData: (previousData, _previousQuery) => previousData,
|
||||
@@ -23,5 +23,11 @@ export default function useSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
return { data: data ?? ontimePlaceholderSettings, status: deriveQueryStatus(status, data), isFetching, isError, refetch };
|
||||
return {
|
||||
data: data ?? ontimePlaceholderSettings,
|
||||
status: deriveQueryStatus(status, isLoadingError),
|
||||
isFetching,
|
||||
isError,
|
||||
refetch,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import { viewsSettingsPlaceholder } from '../models/ViewSettings.type';
|
||||
import { deriveQueryStatus } from '../utils/queryUtils';
|
||||
|
||||
export default function useViewSettings() {
|
||||
const { data, status } = useQuery({
|
||||
const { data, status, isLoadingError } = useQuery({
|
||||
queryKey: VIEW_SETTINGS,
|
||||
queryFn: ({ signal }) => getViewSettings({ signal }),
|
||||
placeholderData: (previousData, _previousQuery) => previousData,
|
||||
@@ -25,5 +25,5 @@ export default function useViewSettings() {
|
||||
},
|
||||
});
|
||||
|
||||
return { data: data ?? viewsSettingsPlaceholder, status: deriveQueryStatus(status, data), mutateAsync };
|
||||
return { data: data ?? viewsSettingsPlaceholder, status: deriveQueryStatus(status, isLoadingError), mutateAsync };
|
||||
}
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
import { deriveQueryStatus } from '../queryUtils';
|
||||
|
||||
test('keeps pending and success statuses unchanged', () => {
|
||||
expect(deriveQueryStatus('pending', undefined)).toBe('pending');
|
||||
expect(deriveQueryStatus('success', { some: 'data' })).toBe('success');
|
||||
expect(deriveQueryStatus('pending', false)).toBe('pending');
|
||||
expect(deriveQueryStatus('success', false)).toBe('success');
|
||||
});
|
||||
|
||||
test('keeps error status when there is no data', () => {
|
||||
expect(deriveQueryStatus('error', undefined)).toBe('error');
|
||||
test('keeps error status on a genuine loading error (no data ever received)', () => {
|
||||
expect(deriveQueryStatus('error', true)).toBe('error');
|
||||
});
|
||||
|
||||
test('downgrades error to success when data is still available', () => {
|
||||
expect(deriveQueryStatus('error', { some: 'data' })).toBe('success');
|
||||
expect(deriveQueryStatus('error', [])).toBe('success');
|
||||
expect(deriveQueryStatus('error', 0)).toBe('success');
|
||||
test('downgrades error to success on a refetch error (data still available)', () => {
|
||||
expect(deriveQueryStatus('error', false)).toBe('success');
|
||||
});
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import type { QueryStatus } from '@tanstack/react-query';
|
||||
|
||||
/**
|
||||
* A background refetch failure still leaves the last successfully fetched data in place.
|
||||
* In that case we want callers to keep treating the query as usable rather than erroring out,
|
||||
* so we only report 'error' when we have never received data for this query.
|
||||
* A background refetch failure (react-query's isRefetchError) still leaves the last
|
||||
* successfully fetched data in place, so we want callers to keep treating the query as
|
||||
* usable rather than erroring out. Only a genuine isLoadingError (never received data)
|
||||
* should surface as 'error'.
|
||||
*/
|
||||
export function deriveQueryStatus(status: QueryStatus, data: unknown): QueryStatus {
|
||||
if (status === 'error' && data !== undefined) {
|
||||
export function deriveQueryStatus(status: QueryStatus, isLoadingError: boolean): QueryStatus {
|
||||
if (status === 'error' && !isLoadingError) {
|
||||
return 'success';
|
||||
}
|
||||
return status;
|
||||
|
||||
Reference in New Issue
Block a user