Skip to content

fix(hitl-edit-panel): move duplicate-tag check into functional setTags (#1248)#1281

Merged
MODSetter merged 1 commit intoMODSetter:devfrom
mvanhorn:osc/1248-handle-add-tag-functional
Apr 21, 2026
Merged

fix(hitl-edit-panel): move duplicate-tag check into functional setTags (#1248)#1281
MODSetter merged 1 commit intoMODSetter:devfrom
mvanhorn:osc/1248-handle-add-tag-functional

Conversation

@mvanhorn
Copy link
Copy Markdown
Contributor

@mvanhorn mvanhorn commented Apr 21, 2026

Summary

Fixes #1248

handleAddTag in EmailsTagField (surfsense_web/components/hitl-edit-panel/hitl-edit-panel.tsx) listed tags in its useCallback dependency array only so the closure-level duplicate check could read it. That had two side effects the issue calls out:

  1. The callback re-created on every tag mutation, invalidating memoization for downstream consumers.
  2. The duplicate check saw closure-level tags, not the latest state, so rapid adds could race.

Change

Move the duplicate check inside the functional setTags updater so it always sees the latest state, and drop tags from the dependency array. The callback is now stable for the component's lifetime.

-const handleAddTag = useCallback(
-    (text: string) => {
-        const trimmed = text.trim();
-        if (!trimmed) return;
-        if (tags.some((tag) => tag.text === trimmed)) return;
-        const newTag: TagType = { id: Date.now().toString(), text: trimmed };
-        setTags((prev) => [...prev, newTag]);
-    },
-    [tags]
-);
+const handleAddTag = useCallback((text: string) => {
+    const trimmed = text.trim();
+    if (!trimmed) return;
+    setTags((prev) => {
+        if (prev.some((tag) => tag.text === trimmed)) return prev;
+        const newTag: TagType = { id: Date.now().toString(), text: trimmed };
+        return [...prev, newTag];
+    });
+}, []);

Testing

  • pnpm biome check components/hitl-edit-panel/hitl-edit-panel.tsx - clean
  • pnpm biome lint components/hitl-edit-panel/hitl-edit-panel.tsx - clean

Pre-existing tsc errors in app/(home)/blog/[slug]/page.tsx are unrelated to this change.

High-level PR Summary

This PR fixes a React hooks optimization issue in the EmailsTagField component by moving the duplicate-tag check from the closure scope into the functional state updater. This eliminates unnecessary callback re-creation on every tag mutation and prevents race conditions when adding tags rapidly, ensuring the duplicate check always sees the latest state while maintaining a stable callback reference.

⏱️ Estimated Review Time: 5-15 minutes

💡 Review Order Suggestion
Order File Path
1 surfsense_web/components/hitl-edit-panel/hitl-edit-panel.tsx

Need help? Join our Discord

Analyze latest changes

Fixes MODSetter#1248

handleAddTag had tags in its useCallback dependency array only so the
closure-level duplicate check could read it, which forced the callback
to re-create on every tag mutation and compared new additions against
a potentially-stale closure value.

Collapse the duplicate check into the functional setTags updater so
the check always runs against the latest state, and drop tags from
the dependency array - the callback is stable for the component's
lifetime and downstream memoization won't get invalidated on every
keystroke.
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 21, 2026

@mvanhorn is attempting to deploy a commit to the Rohan Verma's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 21, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 81c45b7e-6d66-4379-bf3d-ac8d1a0078d9

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@recurseml recurseml Bot left a comment

Choose a reason for hiding this comment

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

Review by RecurseML

🔍 Review performed on 3f30b12..7f0a5cd

✨ No bugs found, your code is sparkling clean

✅ Files analyzed, no issues (1)

surfsense_web/components/hitl-edit-panel/hitl-edit-panel.tsx

@MODSetter MODSetter merged commit 41ff156 into MODSetter:dev Apr 21, 2026
8 of 11 checks passed
@mvanhorn
Copy link
Copy Markdown
Contributor Author

Thanks for the merge, @MODSetter. Functional setTags is the right home for that check.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants