Skip to content

Conversation

@antontranelis
Copy link
Member

Summary

  • Fix stale closure bug in useTags.tsx that prevented addTag from accessing current state
  • Add missing useEffect in PopupView.tsx to persist newly detected hashtags to the database

Problem

Hashtags in item text that didn't exist in the database were not being automatically created. For example, #networking would appear as plain black text instead of being recognized as a hashtag with a color.

Root Causes

1. Stale Closure in addTag (useTags.tsx)

The addTag function used tags and api from the closure scope, which were stale when the function was called:

// Before: stale closure
const addTag = (tag: Tag) => {
  dispatch({ type: 'ADD', tag })
  if (!tags.some(...)) {  // ← tags is stale
    api.createItem && api.createItem(tag)  // ← api is stale
  }
}

2. Missing Persistence (PopupView.tsx)

New tags were detected and collected in newTagsToAdd state, but never actually persisted:

// Tags were added to local state...
setNewTagsToAdd((current) => [...current, newTag])
// ...but never sent to the database

Solution

useTags.tsx

  • Use useRef for apiRef and tagsRef to always access current values
  • Wrap addTag in useCallback with empty dependencies

PopupView.tsx

  • Import useAddTag hook
  • Add useEffect that calls addTag for each new tag when newTagsToAdd changes

Test plan

  • Create an item with a new hashtag (e.g., #testnewtag)
  • Verify the hashtag appears with a random color (not black)
  • Refresh the page and verify the hashtag persists with its color
  • Check the database to confirm the tag was created

🤖 Generated with Claude Code

Two issues were preventing hashtags from being automatically added to the database:

1. **useTags.tsx - Stale closure bug**: The `addTag` function was using
   `tags` and `api` from the closure scope, which were stale when called.
   Fixed by using `useRef` for both `apiRef` and `tagsRef`, ensuring the
   function always accesses current values.

2. **PopupView.tsx - Tag creation in render**: New tags were detected
   inside the render `.map()` function with side effects - an anti-pattern.
   Moved tag processing to a dedicated `processItemsTags` function in
   useTags hook, called via useEffect when items are loaded.

Changes:
- Added `processItemsTags(items: Item[])` function to useTags hook
- Added `useProcessItemsTags` export hook
- Cleaned up PopupView.tsx to use the new hook via useEffect
- Removed side effects from render function

Now when items are loaded, any hashtags that don't exist in the database
are automatically created with a random color.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@antontranelis antontranelis force-pushed the fix/hashtag-auto-creation branch from e483672 to d3e7b7a Compare January 21, 2026 05:39
@mahula mahula changed the title fix(tags): restore automatic hashtag creation for unknown tags fix(lib): restore automatic hashtag creation for unknown tags Jan 24, 2026
@mahula mahula added the bug Something isn't working label Jan 24, 2026
Add comprehensive tests for the useTags hook covering:
- Tag state management (initialization, adding, deduplication)
- API integration (persistence, existing tag handling, stale closure fix)
- Hashtag detection & auto-creation (extraction, skipping known tags, deduplication)
- Tag retrieval (text matching, offers/needs tags, case-insensitive matching)

15 test cases covering the hashtag auto-creation feature addressed in PR #673.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants