diff --git a/.eslintrc.js b/.eslintrc.js index 385d241e52fff..8b3ccafe37f6f 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -979,7 +979,7 @@ module.exports = { 'react-hooks/rules-of-hooks': 'error', // Checks rules of Hooks 'react-hooks/exhaustive-deps': [ 'error', - { additionalHooks: '^(useFetcher|useProgressiveFetcher)$' }, + { additionalHooks: '^(useFetcher|useProgressiveFetcher|useBreadcrumb)$' }, ], }, }, diff --git a/x-pack/plugins/apm/public/components/app/breadcrumb/index.tsx b/x-pack/plugins/apm/public/components/app/breadcrumb/index.tsx index 5cc1293d39f7d..d6afe4a7c1d19 100644 --- a/x-pack/plugins/apm/public/components/app/breadcrumb/index.tsx +++ b/x-pack/plugins/apm/public/components/app/breadcrumb/index.tsx @@ -18,7 +18,10 @@ export const Breadcrumb = ({ children: React.ReactElement; }) => { const { core } = useApmPluginContext(); - useBreadcrumb({ title, href: core.http.basePath.prepend('/app/apm' + href) }); + useBreadcrumb( + () => ({ title, href: core.http.basePath.prepend('/app/apm' + href) }), + [core.http.basePath, href, title] + ); return children; }; diff --git a/x-pack/plugins/apm/public/components/app/dependency_detail_overview/index.tsx b/x-pack/plugins/apm/public/components/app/dependency_detail_overview/index.tsx index 5c259494814a6..e129088b23f68 100644 --- a/x-pack/plugins/apm/public/components/app/dependency_detail_overview/index.tsx +++ b/x-pack/plugins/apm/public/components/app/dependency_detail_overview/index.tsx @@ -30,26 +30,39 @@ export function DependencyDetailOverview() { const apmRouter = useApmRouter(); - useBreadcrumb([ - { - title: i18n.translate( - 'xpack.apm.dependencyDetailOverview.breadcrumbTitle', - { defaultMessage: 'Overview' } - ), - href: apmRouter.link('/dependencies/overview', { - query: { - dependencyName, - rangeFrom, - rangeTo, - refreshInterval, - refreshPaused, - environment, - kuery, - comparisonEnabled, - }, - }), - }, - ]); + useBreadcrumb( + () => [ + { + title: i18n.translate( + 'xpack.apm.dependencyDetailOverview.breadcrumbTitle', + { defaultMessage: 'Overview' } + ), + href: apmRouter.link('/dependencies/overview', { + query: { + dependencyName, + rangeFrom, + rangeTo, + refreshInterval, + refreshPaused, + environment, + kuery, + comparisonEnabled, + }, + }), + }, + ], + [ + apmRouter, + comparisonEnabled, + dependencyName, + environment, + kuery, + rangeFrom, + rangeTo, + refreshInterval, + refreshPaused, + ] + ); return ( <> diff --git a/x-pack/plugins/apm/public/components/app/dependency_detail_view/index.tsx b/x-pack/plugins/apm/public/components/app/dependency_detail_view/index.tsx index a586546cab835..9ad1c2b6e19a0 100644 --- a/x-pack/plugins/apm/public/components/app/dependency_detail_view/index.tsx +++ b/x-pack/plugins/apm/public/components/app/dependency_detail_view/index.tsx @@ -31,36 +31,49 @@ export function DependencyDetailView({ const apmRouter = useApmRouter(); - useBreadcrumb([ - { - title: DependenciesInventoryTitle, - href: apmRouter.link('/dependencies/inventory', { - query: { - rangeFrom, - rangeTo, - refreshInterval, - refreshPaused, - environment, - kuery, - comparisonEnabled, - }, - }), - }, - { - title: dependencyName, - href: apmRouter.link('/dependencies', { - query: { - dependencyName, - rangeFrom, - rangeTo, - refreshInterval, - refreshPaused, - environment, - kuery, - comparisonEnabled, - }, - }), - }, - ]); + useBreadcrumb( + () => [ + { + title: DependenciesInventoryTitle, + href: apmRouter.link('/dependencies/inventory', { + query: { + rangeFrom, + rangeTo, + refreshInterval, + refreshPaused, + environment, + kuery, + comparisonEnabled, + }, + }), + }, + { + title: dependencyName, + href: apmRouter.link('/dependencies', { + query: { + dependencyName, + rangeFrom, + rangeTo, + refreshInterval, + refreshPaused, + environment, + kuery, + comparisonEnabled, + }, + }), + }, + ], + [ + apmRouter, + comparisonEnabled, + dependencyName, + environment, + kuery, + rangeFrom, + rangeTo, + refreshInterval, + refreshPaused, + ] + ); return {children}; } diff --git a/x-pack/plugins/apm/public/components/app/error_group_details/index.tsx b/x-pack/plugins/apm/public/components/app/error_group_details/index.tsx index 7dfaf13e42901..dcde173bffb11 100644 --- a/x-pack/plugins/apm/public/components/app/error_group_details/index.tsx +++ b/x-pack/plugins/apm/public/components/app/error_group_details/index.tsx @@ -127,23 +127,36 @@ export function ErrorGroupDetails() { const { start, end } = useTimeRange({ rangeFrom, rangeTo }); - useBreadcrumb({ - title: groupId, - href: apmRouter.link('/services/{serviceName}/errors/{groupId}', { - path: { - serviceName, - groupId, - }, - query: { - rangeFrom, - rangeTo, - environment, - kuery, - serviceGroup, - comparisonEnabled, - }, + useBreadcrumb( + () => ({ + title: groupId, + href: apmRouter.link('/services/{serviceName}/errors/{groupId}', { + path: { + serviceName, + groupId, + }, + query: { + rangeFrom, + rangeTo, + environment, + kuery, + serviceGroup, + comparisonEnabled, + }, + }), }), - }); + [ + apmRouter, + comparisonEnabled, + environment, + groupId, + kuery, + rangeFrom, + rangeTo, + serviceGroup, + serviceName, + ] + ); const { data: errorGroupData } = useFetcher( (callApmApi) => { diff --git a/x-pack/plugins/apm/public/components/app/service_node_metrics/index.tsx b/x-pack/plugins/apm/public/components/app/service_node_metrics/index.tsx index 9e4fb9b67509f..b902c7f0f1cea 100644 --- a/x-pack/plugins/apm/public/components/app/service_node_metrics/index.tsx +++ b/x-pack/plugins/apm/public/components/app/service_node_metrics/index.tsx @@ -60,19 +60,22 @@ export function ServiceNodeMetrics() { const { start, end } = useTimeRange({ rangeFrom, rangeTo }); - useBreadcrumb({ - title: getServiceNodeName(serviceNodeName), - href: apmRouter.link( - '/services/{serviceName}/nodes/{serviceNodeName}/metrics', - { - path: { - serviceName, - serviceNodeName, - }, - query, - } - ), - }); + useBreadcrumb( + () => ({ + title: getServiceNodeName(serviceNodeName), + href: apmRouter.link( + '/services/{serviceName}/nodes/{serviceNodeName}/metrics', + { + path: { + serviceName, + serviceNodeName, + }, + query, + } + ), + }), + [apmRouter, query, serviceName, serviceNodeName] + ); const { data } = useServiceMetricChartsFetcher({ serviceNodeName, diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/index.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/index.tsx index d91ecf3cb9dab..255cacd0ce2c5 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/index.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/index.tsx @@ -44,13 +44,16 @@ export function TransactionDetails() { replace(history, { query: { transactionType } }); } - useBreadcrumb({ - title: transactionName, - href: apmRouter.link('/services/{serviceName}/transactions/view', { - path, - query, + useBreadcrumb( + () => ({ + title: transactionName, + href: apmRouter.link('/services/{serviceName}/transactions/view', { + path, + query, + }), }), - }); + [apmRouter, path, query, transactionName] + ); const isServerless = isServerlessAgent(runtimeName); diff --git a/x-pack/plugins/apm/public/components/routing/service_detail/apm_service_wrapper.tsx b/x-pack/plugins/apm/public/components/routing/service_detail/apm_service_wrapper.tsx index ef929331f3c1c..cbc20077da29f 100644 --- a/x-pack/plugins/apm/public/components/routing/service_detail/apm_service_wrapper.tsx +++ b/x-pack/plugins/apm/public/components/routing/service_detail/apm_service_wrapper.tsx @@ -19,19 +19,22 @@ export function ApmServiceWrapper() { const router = useApmRouter(); - useBreadcrumb([ - { - title: ServiceInventoryTitle, - href: router.link('/services', { query }), - }, - { - title: serviceName, - href: router.link('/services/{serviceName}', { - query, - path: { serviceName }, - }), - }, - ]); + useBreadcrumb( + () => [ + { + title: ServiceInventoryTitle, + href: router.link('/services', { query }), + }, + { + title: serviceName, + href: router.link('/services/{serviceName}', { + query, + path: { serviceName }, + }), + }, + ], + [query, router, serviceName] + ); return ; } diff --git a/x-pack/plugins/apm/public/components/routing/templates/apm_service_template/index.tsx b/x-pack/plugins/apm/public/components/routing/templates/apm_service_template/index.tsx index da604911aec62..c7dfb07416f2a 100644 --- a/x-pack/plugins/apm/public/components/routing/templates/apm_service_template/index.tsx +++ b/x-pack/plugins/apm/public/components/routing/templates/apm_service_template/index.tsx @@ -86,13 +86,16 @@ function TemplateWithContext({ const tabs = useTabs({ selectedTab }); - useBreadcrumb({ - title, - href: router.link(`/services/{serviceName}/${selectedTab}` as const, { - path: { serviceName }, - query, + useBreadcrumb( + () => ({ + title, + href: router.link(`/services/{serviceName}/${selectedTab}` as const, { + path: { serviceName }, + query, + }), }), - }); + [query, router, selectedTab, serviceName, title] + ); return ( isSelected); - useBreadcrumb([ - { - title: i18n.translate('xpack.apm.serviceGroups.breadcrumb.title', { - defaultMessage: 'Services', - }), - href: serviceGroupsLink, - }, - ...(selectedTab - ? [ - ...(serviceGroupName - ? [ - { - title: serviceGroupName, - href: router.link('/services', { query }), - }, - ] - : []), - { - title: selectedTab.label, - href: selectedTab.href, - } as { title: string; href: string }, - ] - : []), - ]); + useBreadcrumb( + () => [ + { + title: i18n.translate('xpack.apm.serviceGroups.breadcrumb.title', { + defaultMessage: 'Services', + }), + href: serviceGroupsLink, + }, + ...(selectedTab + ? [ + ...(serviceGroupName + ? [ + { + title: serviceGroupName, + href: router.link('/services', { query }), + }, + ] + : []), + { + title: selectedTab.label, + href: selectedTab.href, + } as { title: string; href: string }, + ] + : []), + ], + [query, router, selectedTab, serviceGroupName, serviceGroupsLink] + ); return ( Breadcrumb | Breadcrumb[], + fnDeps: any[] +) { const api = useContext(BreadcrumbsContext); if (!api) { @@ -29,7 +32,7 @@ export function useBreadcrumb(breadcrumb: Breadcrumb | Breadcrumb[]) { matchedRoute.current = match?.route; if (matchedRoute.current) { - api.set(matchedRoute.current, castArray(breadcrumb)); + api.set(matchedRoute.current, castArray(callback())); } return () => { @@ -38,5 +41,5 @@ export function useBreadcrumb(breadcrumb: Breadcrumb | Breadcrumb[]) { } }; // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + }, [match, ...fnDeps]); } diff --git a/x-pack/plugins/apm/public/hooks/use_dependency_detail_operations_breadcrumb.ts b/x-pack/plugins/apm/public/hooks/use_dependency_detail_operations_breadcrumb.ts index 1364b2a38231d..a2db87adadc51 100644 --- a/x-pack/plugins/apm/public/hooks/use_dependency_detail_operations_breadcrumb.ts +++ b/x-pack/plugins/apm/public/hooks/use_dependency_detail_operations_breadcrumb.ts @@ -26,24 +26,37 @@ export function useDependencyDetailOperationsBreadcrumb() { const apmRouter = useApmRouter(); - useBreadcrumb([ - { - title: i18n.translate( - 'xpack.apm.dependencyDetailOperations.breadcrumbTitle', - { defaultMessage: 'Operations' } - ), - href: apmRouter.link('/dependencies/operations', { - query: { - dependencyName, - rangeFrom, - rangeTo, - refreshInterval, - refreshPaused, - environment, - kuery, - comparisonEnabled, - }, - }), - }, - ]); + useBreadcrumb( + () => [ + { + title: i18n.translate( + 'xpack.apm.dependencyDetailOperations.breadcrumbTitle', + { defaultMessage: 'Operations' } + ), + href: apmRouter.link('/dependencies/operations', { + query: { + dependencyName, + rangeFrom, + rangeTo, + refreshInterval, + refreshPaused, + environment, + kuery, + comparisonEnabled, + }, + }), + }, + ], + [ + apmRouter, + comparisonEnabled, + dependencyName, + environment, + kuery, + rangeFrom, + rangeTo, + refreshInterval, + refreshPaused, + ] + ); }