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,
+ ]
+ );
}