From 52451ec5ed599b9e77f358b3e9eda2ae33219cbd Mon Sep 17 00:00:00 2001 From: Mason Woodford <63433735+masonwoodford@users.noreply.github.com> Date: Wed, 25 Sep 2024 03:22:59 +0900 Subject: [PATCH] FE: Fix refetching data on window focus (#380) Co-authored-by: Roman Zabaluev --- frontend/src/components/Schemas/Edit/Edit.tsx | 12 ++++-- .../src/components/Topics/Topic/Edit/Edit.tsx | 15 +++++-- frontend/src/lib/constants.ts | 5 +++ .../lib/hooks/api/__tests__/schema.spec.ts | 11 +++++ .../lib/hooks/api/__tests__/topics.spec.ts | 41 ++++++++++++++----- frontend/src/lib/hooks/api/schemas.ts | 13 +++++- frontend/src/lib/hooks/api/topics.ts | 30 +++++++++++--- 7 files changed, 103 insertions(+), 24 deletions(-) diff --git a/frontend/src/components/Schemas/Edit/Edit.tsx b/frontend/src/components/Schemas/Edit/Edit.tsx index 2e6892197..6e8c04230 100644 --- a/frontend/src/components/Schemas/Edit/Edit.tsx +++ b/frontend/src/components/Schemas/Edit/Edit.tsx @@ -4,6 +4,7 @@ import useAppParams from 'lib/hooks/useAppParams'; import PageLoader from 'components/common/PageLoader/PageLoader'; import { useNavigate } from 'react-router-dom'; import { useGetLatestSchema } from 'lib/hooks/api/schemas'; +import { QUERY_REFETCH_LIMITED_OPTIONS } from 'lib/constants'; import Form from './Form'; @@ -14,10 +15,13 @@ const Edit: React.FC = () => { isFetching, isError, data: schema, - } = useGetLatestSchema({ - clusterName, - subject, - }); + } = useGetLatestSchema( + { + clusterName, + subject, + }, + QUERY_REFETCH_LIMITED_OPTIONS + ); useEffect(() => { if (isError) { diff --git a/frontend/src/components/Topics/Topic/Edit/Edit.tsx b/frontend/src/components/Topics/Topic/Edit/Edit.tsx index 598ac5982..1d02bd598 100644 --- a/frontend/src/components/Topics/Topic/Edit/Edit.tsx +++ b/frontend/src/components/Topics/Topic/Edit/Edit.tsx @@ -7,7 +7,10 @@ import { yupResolver } from '@hookform/resolvers/yup'; import { topicFormValidationSchema } from 'lib/yupExtended'; import useAppParams from 'lib/hooks/useAppParams'; import topicParamsTransformer from 'components/Topics/Topic/Edit/topicParamsTransformer'; -import { MILLISECONDS_IN_WEEK } from 'lib/constants'; +import { + MILLISECONDS_IN_WEEK, + QUERY_REFETCH_LIMITED_OPTIONS, +} from 'lib/constants'; import { useTopicConfig, useTopicDetails, @@ -30,8 +33,14 @@ export const TOPIC_EDIT_FORM_DEFAULT_PROPS = { const Edit: React.FC = () => { const { clusterName, topicName } = useAppParams(); - const { data: topic } = useTopicDetails({ clusterName, topicName }); - const { data: topicConfig } = useTopicConfig({ clusterName, topicName }); + const { data: topic } = useTopicDetails( + { clusterName, topicName }, + QUERY_REFETCH_LIMITED_OPTIONS + ); + const { data: topicConfig } = useTopicConfig( + { clusterName, topicName }, + QUERY_REFETCH_LIMITED_OPTIONS + ); const updateTopic = useUpdateTopic({ clusterName, topicName }); const defaultValues = topicParamsTransformer(topic, topicConfig); diff --git a/frontend/src/lib/constants.ts b/frontend/src/lib/constants.ts index 3d765ee0a..3e3925ec9 100644 --- a/frontend/src/lib/constants.ts +++ b/frontend/src/lib/constants.ts @@ -73,6 +73,11 @@ export const QUERY_REFETCH_OFF_OPTIONS = { refetchIntervalInBackground: false, }; +export const QUERY_REFETCH_LIMITED_OPTIONS = { + refetchOnWindowFocus: false, + refetchIntervalInBackground: false, +}; + // Cluster Form Constants export const AUTH_OPTIONS = [ { value: 'SASL/JAAS', label: 'SASL/JAAS' }, diff --git a/frontend/src/lib/hooks/api/__tests__/schema.spec.ts b/frontend/src/lib/hooks/api/__tests__/schema.spec.ts index eea7c94b8..7dbfc8700 100644 --- a/frontend/src/lib/hooks/api/__tests__/schema.spec.ts +++ b/frontend/src/lib/hooks/api/__tests__/schema.spec.ts @@ -5,6 +5,7 @@ import { } from 'lib/testHelpers'; import fetchMock from 'fetch-mock'; import * as hooks from 'lib/hooks/api/schemas'; +import { QUERY_REFETCH_LIMITED_OPTIONS } from 'lib/constants'; import { act } from 'react-dom/test-utils'; import { renderHook, waitFor } from '@testing-library/react'; import { CompatibilityLevelCompatibilityEnum } from 'generated-sources'; @@ -47,6 +48,16 @@ describe('Schema hooks', () => { ); await expectQueryWorks(mock, result); }); + it('returns the correct data with queryOptions', async () => { + const mock = fetchMock.getOnce(schemasAPILatestUrl, schemaVersion); + const { result } = renderQueryHook(() => + hooks.useGetLatestSchema( + { clusterName, subject }, + QUERY_REFETCH_LIMITED_OPTIONS + ) + ); + await expectQueryWorks(mock, result); + }); }); describe('useGetSchemasVersions', () => { diff --git a/frontend/src/lib/hooks/api/__tests__/topics.spec.ts b/frontend/src/lib/hooks/api/__tests__/topics.spec.ts index 6007f3356..9085014fd 100644 --- a/frontend/src/lib/hooks/api/__tests__/topics.spec.ts +++ b/frontend/src/lib/hooks/api/__tests__/topics.spec.ts @@ -9,6 +9,7 @@ import fetchMock from 'fetch-mock'; import { externalTopicPayload, topicConfigPayload } from 'lib/fixtures/topics'; import { CreateTopicMessage } from 'generated-sources'; import { TopicFormData, TopicFormDataRaw } from 'lib/interfaces/topic'; +import { QUERY_REFETCH_LIMITED_OPTIONS } from 'lib/constants'; const clusterName = 'test-cluster'; const topicName = 'test-topic'; @@ -30,17 +31,37 @@ describe('Topics hooks', () => { const { result } = renderQueryHook(() => hooks.useTopics({ clusterName })); await expectQueryWorks(mock, result); }); - it('handles useTopicDetails', async () => { - const mock = fetchMock.getOnce(topicPath, externalTopicPayload); - const { result } = renderQueryHook(() => - hooks.useTopicDetails(topicParams) - ); - await expectQueryWorks(mock, result); + describe('useTopicDetails', () => { + it('handles useTopicDetails', async () => { + const mock = fetchMock.getOnce(topicPath, externalTopicPayload); + const { result } = renderQueryHook(() => + hooks.useTopicDetails(topicParams) + ); + await expectQueryWorks(mock, result); + }); + it('handles useTopicDetails with queryOptions', async () => { + const mock = fetchMock.getOnce(topicPath, externalTopicPayload); + const { result } = renderQueryHook(() => + hooks.useTopicDetails(topicParams, QUERY_REFETCH_LIMITED_OPTIONS) + ); + await expectQueryWorks(mock, result); + }); }); - it('handles useTopicConfig', async () => { - const mock = fetchMock.getOnce(`${topicPath}/config`, topicConfigPayload); - const { result } = renderQueryHook(() => hooks.useTopicConfig(topicParams)); - await expectQueryWorks(mock, result); + describe('useTopicConfig', () => { + it('handles useTopicConfig', async () => { + const mock = fetchMock.getOnce(`${topicPath}/config`, topicConfigPayload); + const { result } = renderQueryHook(() => + hooks.useTopicConfig(topicParams) + ); + await expectQueryWorks(mock, result); + }); + it('handles useTopicConfig with queryOptions', async () => { + const mock = fetchMock.getOnce(`${topicPath}/config`, topicConfigPayload); + const { result } = renderQueryHook(() => + hooks.useTopicConfig(topicParams, QUERY_REFETCH_LIMITED_OPTIONS) + ); + await expectQueryWorks(mock, result); + }); }); it('handles useTopicConsumerGroups', async () => { const mock = fetchMock.getOnce(`${topicPath}/consumer-groups`, []); diff --git a/frontend/src/lib/hooks/api/schemas.ts b/frontend/src/lib/hooks/api/schemas.ts index 7082d180a..aeb1ed9a6 100644 --- a/frontend/src/lib/hooks/api/schemas.ts +++ b/frontend/src/lib/hooks/api/schemas.ts @@ -1,4 +1,9 @@ -import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; +import { + useMutation, + useQuery, + useQueryClient, + UseQueryOptions, +} from '@tanstack/react-query'; import { GLOBAL_COMPATIBILITY_SCHEMAS_QUERY_KEY, LATEST_SCHEMA_QUERY_KEY, @@ -19,7 +24,10 @@ import { import { schemasApiClient } from 'lib/api'; import { ClusterName } from 'lib/interfaces/cluster'; -export function useGetLatestSchema(param: GetLatestSchemaRequest) { +export function useGetLatestSchema( + param: GetLatestSchemaRequest, + options?: UseQueryOptions +) { return useQuery({ queryKey: [ SCHEMA_QUERY_KEY, @@ -28,6 +36,7 @@ export function useGetLatestSchema(param: GetLatestSchemaRequest) { param.subject, ], queryFn: () => schemasApiClient.getLatestSchema(param), + ...options, }); } diff --git a/frontend/src/lib/hooks/api/topics.ts b/frontend/src/lib/hooks/api/topics.ts index b0aac312d..fb05ee219 100644 --- a/frontend/src/lib/hooks/api/topics.ts +++ b/frontend/src/lib/hooks/api/topics.ts @@ -4,7 +4,12 @@ import { consumerGroupsApiClient, messagesApiClient, } from 'lib/api'; -import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; +import { + useMutation, + useQuery, + useQueryClient, + UseQueryOptions, +} from '@tanstack/react-query'; import { CreateTopicMessage, GetTopicDetailsRequest, @@ -12,6 +17,7 @@ import { Topic, TopicConfig, TopicCreation, + TopicDetails, TopicUpdate, } from 'generated-sources'; import { showServerError, showSuccessAlert } from 'lib/errorHandling'; @@ -49,11 +55,25 @@ export function useTopics(props: GetTopicsRequest) { { keepPreviousData: true } ); } -export function useTopicDetails(props: GetTopicDetailsRequest) { - return useQuery(topicKeys.details(props), () => api.getTopicDetails(props)); +export function useTopicDetails( + props: GetTopicDetailsRequest, + queryOptions?: UseQueryOptions +) { + return useQuery( + topicKeys.details(props), + () => api.getTopicDetails(props), + queryOptions + ); } -export function useTopicConfig(props: GetTopicDetailsRequest) { - return useQuery(topicKeys.config(props), () => api.getTopicConfigs(props)); +export function useTopicConfig( + props: GetTopicDetailsRequest, + queryOptions?: UseQueryOptions +) { + return useQuery( + topicKeys.config(props), + () => api.getTopicConfigs(props), + queryOptions + ); } export function useTopicConsumerGroups(props: GetTopicDetailsRequest) { return useQuery(topicKeys.consumerGroups(props), () =>