Skip to content

Commit 9f13618

Browse files
committed
Simplify using hook
1 parent ad5ccee commit 9f13618

File tree

3 files changed

+44
-80
lines changed

3 files changed

+44
-80
lines changed

static/app/views/explore/metrics/equationBuilder.tsx

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -122,18 +122,25 @@ export function EquationBuilder({
122122
}
123123
}, [referenceMap, internalExpression, handleExpressionChange]);
124124

125+
// Report which labels this equation references after unresolving.
126+
// Cleans up on unmount so deleted equations don't block metric deletion.
127+
useEffect(() => {
128+
const expr = new Expression(internalExpression, references);
129+
onReferenceLabelsChange?.(extractReferenceLabels(expr));
130+
return () => {
131+
onReferenceLabelsChange?.([]);
132+
};
133+
}, [internalExpression, references, onReferenceLabelsChange]);
134+
125135
const handleInternalExpressionChange = useCallback(
126136
(newExpression: Expression) => {
127137
startTransition(() => {
128138
if (newExpression.isValid) {
129-
// Report the labels from the pre-resolved expression so the
130-
// caller knows exactly which labels (A, B, etc.) were typed.
131-
onReferenceLabelsChange?.(extractReferenceLabels(newExpression));
132139
handleExpressionChange(resolveExpression(newExpression, referenceMap));
133140
}
134141
});
135142
},
136-
[handleExpressionChange, onReferenceLabelsChange, referenceMap]
143+
[handleExpressionChange, referenceMap]
137144
);
138145

139146
return (
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import {useCallback, useMemo, useState} from 'react';
2+
3+
/**
4+
* Tracks which metric labels (A, B, etc.) are referenced by equations.
5+
* Each EquationBuilder reports its labels via onEquationLabelsChange after
6+
* unresolving its expression. The aggregate set is derived from state.
7+
*/
8+
export function useEquationReferencedLabels() {
9+
const [equationLabels, onEquationLabelsChangeState] = useState(
10+
new Map<string, string[]>()
11+
);
12+
13+
const onEquationLabelsChange = useCallback(
14+
(equationLabel: string, labels: string[]) => {
15+
onEquationLabelsChangeState(prev => new Map(prev).set(equationLabel, labels));
16+
},
17+
[]
18+
);
19+
20+
const referencedMetricLabels = useMemo(() => {
21+
const set = new Set<string>();
22+
for (const labels of equationLabels.values()) {
23+
for (const label of labels) {
24+
set.add(label);
25+
}
26+
}
27+
return set;
28+
}, [equationLabels]);
29+
30+
return {referencedMetricLabels, onEquationLabelsChange};
31+
}

static/app/views/explore/metrics/metricsTab.tsx

Lines changed: 2 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {Fragment, useCallback, useMemo, useState} from 'react';
1+
import {Fragment} from 'react';
22
import {closestCenter, DndContext} from '@dnd-kit/core';
33
import {SortableContext, verticalListSortingStrategy} from '@dnd-kit/sortable';
44
import styled from '@emotion/styled';
@@ -23,6 +23,7 @@ import {
2323
import {ToolbarVisualizeAddChart} from 'sentry/views/explore/components/toolbar/toolbarVisualize';
2424
import {useMetricsAnalytics} from 'sentry/views/explore/hooks/useAnalytics';
2525
import {useMetricOptions} from 'sentry/views/explore/hooks/useMetricOptions';
26+
import {useEquationReferencedLabels} from 'sentry/views/explore/metrics/hooks/useEquationReferencedLabels';
2627
import {useMetricReferences} from 'sentry/views/explore/metrics/hooks/useMetricReferences';
2728
import {useSortableMetricQueries} from 'sentry/views/explore/metrics/hooks/useSortableMetricQueries';
2829
import {MetricPanel} from 'sentry/views/explore/metrics/metricPanel';
@@ -47,81 +48,6 @@ import {
4748
import {isVisualizeEquation} from 'sentry/views/explore/queryParams/visualize';
4849
export const METRICS_CHART_GROUP = 'metrics-charts-group';
4950

50-
/**
51-
* Tracks which metric labels (A, B, etc.) are referenced by equations.
52-
*
53-
* On initial load, labels are precomputed by reverse-resolving each
54-
* equation's stored expression against the referenceMap. When the user
55-
* edits an equation, the EquationBuilder reports the exact labels that
56-
* were typed, which override the precomputed values for that equation.
57-
*/
58-
function useEquationReferencedLabels() {
59-
const metricQueries = useMultiMetricsQueryParams();
60-
const referenceMap = useMetricReferences();
61-
62-
// User-reported labels from equation edits override precomputed values
63-
const [userLabelsByEquation, setUserLabelsByEquation] = useState<
64-
Map<string, readonly string[]>
65-
>(() => new Map());
66-
67-
const onEquationLabelsChange = useCallback(
68-
(equationLabel: string, labels: string[]) => {
69-
setUserLabelsByEquation(prev => {
70-
const current = prev.get(equationLabel);
71-
if (
72-
current?.length === labels.length &&
73-
current.every((l, i) => l === labels[i])
74-
) {
75-
return prev;
76-
}
77-
const next = new Map(prev);
78-
next.set(equationLabel, labels);
79-
return next;
80-
});
81-
},
82-
[]
83-
);
84-
85-
const referencedMetricLabels = useMemo(() => {
86-
// Build reverse map (function string → first label) for precomputation
87-
const reversedReferenceMap: Record<string, string> = {};
88-
for (const [label, functionString] of Object.entries(referenceMap)) {
89-
if (!reversedReferenceMap[functionString]) {
90-
reversedReferenceMap[functionString] = label;
91-
}
92-
}
93-
94-
const set = new Set<string>();
95-
for (const q of metricQueries) {
96-
const v = q.queryParams.visualizes[0];
97-
if (!v || !isVisualizeEquation(v)) {
98-
continue;
99-
}
100-
101-
const eqLabel = q.label ?? '';
102-
const userLabels = userLabelsByEquation.get(eqLabel);
103-
104-
if (userLabels) {
105-
// Use user-reported labels (from explicit equation edits)
106-
for (const label of userLabels) {
107-
set.add(label);
108-
}
109-
} else {
110-
// Precompute from stored expression via reverse-resolve
111-
for (const token of v.expression.tokens) {
112-
const referencedLabel = reversedReferenceMap[token.text];
113-
if (referencedLabel) {
114-
set.add(referencedLabel);
115-
}
116-
}
117-
}
118-
}
119-
return set;
120-
}, [metricQueries, referenceMap, userLabelsByEquation]);
121-
122-
return {referencedMetricLabels, onEquationLabelsChange};
123-
}
124-
12551
type MetricsTabProps = {
12652
datePageFilterProps: DatePageFilterProps;
12753
};

0 commit comments

Comments
 (0)