diff --git a/public/app/core/components/NestedFolderPicker/FolderRepo.tsx b/public/app/core/components/NestedFolderPicker/FolderRepo.tsx index 153becab1b9..9de19c4fcfe 100644 --- a/public/app/core/components/NestedFolderPicker/FolderRepo.tsx +++ b/public/app/core/components/NestedFolderPicker/FolderRepo.tsx @@ -14,13 +14,12 @@ export interface Props { } export const FolderRepo = memo(function FolderRepo({ folder }: Props) { - // skip rendering if: - // folder is not present - // folder have parentUID - // folder is not managed - // if whole instance is provisioned - const isProvisionedInstance = useIsProvisionedInstance(); - const skipRender = getShouldSkipRender(folder, isProvisionedInstance); + // Check if we can skip early without needing the useIsProvisionedInstance query + // This reduces RTK Query subscriptions and prevents re-render loops on API errors + const canSkipEarly = getCanSkipEarly(folder); + + const isProvisionedInstance = useIsProvisionedInstance({ skip: canSkipEarly }); + const skipRender = canSkipEarly || isProvisionedInstance; const { isReadOnlyRepo, repoType } = useGetResourceRepositoryView({ folderName: skipRender ? undefined : folder?.uid, @@ -51,11 +50,19 @@ export const FolderRepo = memo(function FolderRepo({ folder }: Props) { ); }); -function getShouldSkipRender(folder: FolderDTO | DashboardViewItem | undefined, isProvisionedInstance?: boolean) { - // Skip render if parentUID is present, then we should skip rendering. we only display icon for root folders - const hasParent = folder && Boolean('parentUID' in folder && folder.parentUID); - // Skip render if folder is not managed by Repo - const isNotManaged = folder && folder.managedBy !== ManagerKind.Repo; - - return !folder || hasParent || isNotManaged || isProvisionedInstance; +// Check conditions that don't require the useIsProvisionedInstance hook +function getCanSkipEarly(folder: FolderDTO | DashboardViewItem | undefined): boolean { + if (!folder) { + return true; + } + // Skip render if parentUID is present - we only display icon for root folders + const hasParent = Boolean('parentUID' in folder && folder.parentUID); + if (hasParent) { + return true; + } + const isNotManaged = folder.managedBy !== ManagerKind.Repo; + if (isNotManaged) { + return true; + } + return false; } diff --git a/public/app/features/browse-dashboards/components/BrowseView.tsx b/public/app/features/browse-dashboards/components/BrowseView.tsx index b28204f4fe2..0b42b79f9ae 100644 --- a/public/app/features/browse-dashboards/components/BrowseView.tsx +++ b/public/app/features/browse-dashboards/components/BrowseView.tsx @@ -43,10 +43,10 @@ export function BrowseView({ folderUID, width, height, permissions, isReadOnlyRe const selectedItems = useCheckboxSelectionState(); const childrenByParentUID = useChildrenByParentUIDState(); const canSelect = canSelectItems(permissions); - const isProvisionedInstance = useIsProvisionedInstance(); const provisioningEnabled = config.featureToggles.provisioning; const hasNoRole = contextSrv.user.orgRole === OrgRole.None; const { data: settingsData } = useGetFrontendSettingsQuery(!provisioningEnabled || hasNoRole ? skipToken : undefined); + const isProvisionedInstance = useIsProvisionedInstance({ settings: settingsData }); const rootItems = useSelector(rootItemsSelector); const [, stateManager] = useSearchStateManager(); diff --git a/public/app/features/provisioning/hooks/useGetResourceRepositoryView.ts b/public/app/features/provisioning/hooks/useGetResourceRepositoryView.ts index d612be620dc..9dc8e2b51c1 100644 --- a/public/app/features/provisioning/hooks/useGetResourceRepositoryView.ts +++ b/public/app/features/provisioning/hooks/useGetResourceRepositoryView.ts @@ -34,9 +34,10 @@ export const useGetResourceRepositoryView = ({ const hasNoRole = contextSrv.user.orgRole === OrgRole.None; const provisioningEnabled = config.featureToggles.provisioning; - const { data: settingsData, isLoading: isSettingsLoading } = useGetFrontendSettingsQuery( - !provisioningEnabled || skipQuery || hasNoRole ? skipToken : undefined - ); + const shouldSkipSettings = !provisioningEnabled || skipQuery || hasNoRole || (!name && !folderName); + const settingsQueryArg = shouldSkipSettings ? skipToken : undefined; + + const { data: settingsData, isLoading: isSettingsLoading } = useGetFrontendSettingsQuery(settingsQueryArg); const skipFolderQuery = !folderName || !provisioningEnabled || skipQuery || hasNoRole; const { data: folder, isLoading: isFolderLoading } = useGetFolderQuery( diff --git a/public/app/features/provisioning/hooks/useIsProvisionedInstance.ts b/public/app/features/provisioning/hooks/useIsProvisionedInstance.ts index 1c4ba12b8e4..61fcbb73da6 100644 --- a/public/app/features/provisioning/hooks/useIsProvisionedInstance.ts +++ b/public/app/features/provisioning/hooks/useIsProvisionedInstance.ts @@ -5,13 +5,22 @@ import { config } from '@grafana/runtime'; import { RepositoryViewList, useGetFrontendSettingsQuery } from 'app/api/clients/provisioning/v0alpha1'; import { contextSrv } from 'app/core/services/context_srv'; -export function useIsProvisionedInstance(settings?: RepositoryViewList) { +interface UseIsProvisionedInstanceOptions { + settings?: RepositoryViewList; + skip?: boolean; +} + +export function useIsProvisionedInstance(options: UseIsProvisionedInstanceOptions = {}) { + const { settings, skip: skipQuery } = options; const hasNoRole = contextSrv.user.orgRole === OrgRole.None; - const skip = !config.featureToggles.provisioning || hasNoRole; + const skip = !config.featureToggles.provisioning || hasNoRole || skipQuery; const settingsQuery = useGetFrontendSettingsQuery(settings || skip ? skipToken : undefined); - if (!settings) { - settings = settingsQuery.data; + + if (settingsQuery.isError) { + return false; } - return settings?.items?.some((item) => item.target === 'instance'); + + const effectiveSettings = settings ?? settingsQuery.data; + return effectiveSettings?.items?.some((item) => item.target === 'instance'); }