Skip to content

ref(performance): convert TransactionThresholdModal from class to function component#109574

Merged
JoshuaKGoldberg merged 1 commit intomasterfrom
function-component-transaction-threshold-modal
Mar 6, 2026
Merged

ref(performance): convert TransactionThresholdModal from class to function component#109574
JoshuaKGoldberg merged 1 commit intomasterfrom
function-component-transaction-threshold-modal

Conversation

@JoshuaKGoldberg
Copy link
Member

@JoshuaKGoldberg JoshuaKGoldberg commented Feb 27, 2026

Extracts a shared useEventViewProject memo hook from the TransactionThresholdButton component as created in #109567.

Streamlines two things from the class component version:

  • It was using dynamic this.state[field] setting with lodash/set; now it's direct set* hook setter calls
  • state.error was never used for anything (errors are registered with addErrorMessage); now it's removed

Stacked on #109567. I'll keep this as a draft for reference for now.

Fixes EXP-809

@linear
Copy link

linear bot commented Mar 2, 2026

Base automatically changed from function-component-transaction-threshold-button to master March 4, 2026 22:30
@JoshuaKGoldberg JoshuaKGoldberg force-pushed the function-component-transaction-threshold-modal branch from 1148517 to 3518b34 Compare March 4, 2026 22:32
transactionThreshold,
transactionThresholdMetric,
}: Props) {
const [threshold, setThreshold] = useState<number | string | undefined>(
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

number | string | undefined

This seemed strange at first. But the threshold really is stored as sometimes a number (setThreshold(data.threshold);), sometimes a string (setThreshold(event.target.value);). Refactoring to parse the string / use event.target.valueAsNumber would be a bigger change.

@JoshuaKGoldberg JoshuaKGoldberg force-pushed the function-component-transaction-threshold-modal branch from 3518b34 to fb3127f Compare March 4, 2026 22:35
@JoshuaKGoldberg JoshuaKGoldberg marked this pull request as ready for review March 4, 2026 22:43
@JoshuaKGoldberg JoshuaKGoldberg requested a review from a team as a code owner March 4, 2026 22:43
Copy link
Contributor

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Autofix Details

Bugbot Autofix prepared fixes for both issues found in the latest run.

  • ✅ Fixed: Dropped project prop causes wrong project in modal
    • Updated useEventViewProject to accept optional project parameter and check it first before falling back to eventView.project[0], ensuring the correct project is used in multi-project views.
  • ✅ Fixed: DELETE request error handler completely removed in reset
    • Added .catch() block to DELETE request chain in handleReset with proper error handling via addErrorMessage, preventing unhandled promise rejections.

Create PR

Or push these changes by commenting:

@cursor push 61dfc50bc6
Preview (61dfc50bc6)
diff --git a/static/app/views/performance/transactionSummary/projectUtils.ts b/static/app/views/performance/transactionSummary/projectUtils.ts
--- a/static/app/views/performance/transactionSummary/projectUtils.ts
+++ b/static/app/views/performance/transactionSummary/projectUtils.ts
@@ -4,14 +4,22 @@
 import {defined} from 'sentry/utils';
 import type EventView from 'sentry/utils/discover/eventView';
 
-export function useEventViewProject(eventView: EventView, projects: Project[]) {
+export function useEventViewProject(
+  eventView: EventView,
+  projects: Project[],
+  project?: string
+) {
   return useMemo(() => {
     if (!defined(eventView)) {
       return undefined;
     }
 
+    if (defined(project)) {
+      return projects.find(proj => proj.id === project);
+    }
+
     const projectId = String(eventView.project[0]);
 
     return projects.find(proj => proj.id === projectId);
-  }, [eventView, projects]);
+  }, [eventView, projects, project]);
 }

diff --git a/static/app/views/performance/transactionSummary/transactionThresholdModal.tsx b/static/app/views/performance/transactionSummary/transactionThresholdModal.tsx
--- a/static/app/views/performance/transactionSummary/transactionThresholdModal.tsx
+++ b/static/app/views/performance/transactionSummary/transactionThresholdModal.tsx
@@ -55,6 +55,7 @@
   organization,
   closeModal,
   onApply,
+  project: projectProp,
   projects,
   transactionName,
   transactionThreshold,
@@ -66,7 +67,7 @@
   const [metric, setMetric] = useState<TransactionThresholdMetric | undefined>(
     transactionThresholdMetric
   );
-  const project = useEventViewProject(eventView, projects);
+  const project = useEventViewProject(eventView, projects, projectProp);
 
   const handleApply = (event: React.FormEvent) => {
     event.preventDefault();
@@ -148,6 +149,14 @@
             const errorMessage = err.responseJSON?.threshold ?? null;
             addErrorMessage(errorMessage);
           });
+      })
+      .catch(err => {
+        let errorMessage =
+          err.responseJSON?.threshold ?? err.responseJSON?.non_field_errors ?? null;
+        if (Array.isArray(errorMessage)) {
+          errorMessage = errorMessage[0];
+        }
+        addErrorMessage(errorMessage);
       });
   };
This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.

Copy link
Contributor

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

@JoshuaKGoldberg JoshuaKGoldberg force-pushed the function-component-transaction-threshold-modal branch 2 times, most recently from 50467c3 to 6cd8a2a Compare March 5, 2026 14:37
.then(() => {
const projectThresholdUrl = `/projects/${organization.slug}/${project.slug}/transaction-threshold/configure/`;
this.props.api
return api
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note the intentional added return: this unifies the two .catch() clauses into one. this.state.error was previously unused. Now they both go into addErrorMessage.

Copy link
Member

@gggritso gggritso left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sweet!

@JoshuaKGoldberg JoshuaKGoldberg force-pushed the function-component-transaction-threshold-modal branch from 6cd8a2a to bb3efea Compare March 6, 2026 12:35
@JoshuaKGoldberg JoshuaKGoldberg merged commit 3e0f231 into master Mar 6, 2026
61 checks passed
@JoshuaKGoldberg JoshuaKGoldberg deleted the function-component-transaction-threshold-modal branch March 6, 2026 13:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Frontend Automatically applied to PRs that change frontend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants