Skip to content

fix: prevent duplicate conversation creation and improve chat state persistence#116

Open
santinoo1919 wants to merge 9 commits intodarkresearch:mainfrom
santinoo1919:fix/prevent-new-conversation-on-tab-switch
Open

fix: prevent duplicate conversation creation and improve chat state persistence#116
santinoo1919 wants to merge 9 commits intodarkresearch:mainfrom
santinoo1919:fix/prevent-new-conversation-on-tab-switch

Conversation

@santinoo1919
Copy link

@santinoo1919 santinoo1919 commented Jan 21, 2026

Description

Fixes #85 - Infinite chats creation when navigating back-forth to modals

This PR fixes (temporarily) chat state persistence issues when switching between tabs/modals on mobile web. The main issue was that every time a user navigated away from the chat screen (to wallet, account, or chat history) and returned, a new conversation was being created instead of preserving the existing one.

Key fixes:

  • Prevent new conversations from being created on tab switch by checking context and storage before creating
  • Preserve conversationId in URL when navigating to chat tab (web-specific)
  • Add context conversationId as Priority 2 check to prevent duplicate creation
  • Manually insert new conversations for instant visibility
  • Sort conversations after inserting new chat to ensure latest appears at top
  • Improve conversation creation error handling with timeouts
  • Reload messages when returning to conversation with no messages

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Release (version bump)

Release

Is this a release? No - this is a bug fix. Maintainers will handle versioning when merging.

Testing

Tested scenarios:

  • ✅ Tab switching between chat and wallet tabs on mobile web
  • ✅ Tab switching between chat and account tabs
  • ✅ Opening chat history modal and returning to chat
  • ✅ Verified no duplicate conversations are created
  • ✅ Confirmed messages persist after tab switch
  • ✅ Verified new chats appear instantly in history panel
  • ✅ Tested conversation creation with timeout handling
  • ✅ Verified URL preserves conversationId on web

Test environment:

  • Mobile web browser (iOS Safari, Chrome)
  • Desktop web browser (Chrome, Safari)

Checklist

  • My code follows the project's style guidelines
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • My changes generate no new warnings or errors
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing tests pass locally with my changes
  • If releasing, I have verified the version number is correct and follows semantic versioning

- Prevents conversationId from being lost when switching tabs
- Reads from storage and includes in URL for web navigation
- Fixes issue where chat would reload unnecessarily when switching tabs
- Add race condition protection with isLoadingRef
- Add retry logic with 100ms delay for storage reads
- Only create new conversation if none exists after retry
- Prevents duplicate conversations when switching tabs
- Check if messages exist before skipping reload
- Reset refs to allow reload if same conversation has no messages
- Prevents empty chat when switching back to previous conversation
- Add 15s timeout guard to prevent hanging loading state
- Add 10s timeout for createNewConversation promise
- Improve error handling and state cleanup
- Remove verbose debug logging from createConversationDirectly
- Simplify auth flow by using provided userId first
- Add timeout handling for auth operations
…tion

- Add Priority 2 check for contextConversationId before checking storage
- Use context conversationId if available (fastest path)
- Update URL for web to preserve conversationId
- Prevents unnecessary new conversation creation
Copy link

@vercel vercel bot left a comment

Choose a reason for hiding this comment

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

Additional Suggestion:

The contextConversationId is used in the effect but is not included in the dependency array, violating React's Rules of Hooks and potentially missing updates to the context value.

View Details
📝 Patch Details
diff --git a/apps/client/hooks/useActiveConversation.ts b/apps/client/hooks/useActiveConversation.ts
index f20937d..de5684f 100644
--- a/apps/client/hooks/useActiveConversation.ts
+++ b/apps/client/hooks/useActiveConversation.ts
@@ -141,7 +141,7 @@ export function useActiveConversation({ userId }: UseActiveConversationProps) {
     };
 
     loadActiveConversation();
-  }, [userId, params.conversationId]);
+  }, [userId, params.conversationId, contextConversationId]);
 
   return {
     conversationId,

Analysis

Missing dependency in useActiveConversation effect violates React Rules of Hooks

What fails: The useActiveConversation hook uses contextConversationId inside the effect (Priority 2 logic checks if a conversation exists in the global context) but does not include it in the dependency array [userId, params.conversationId].

How to reproduce:

  1. Run ESLint with react-hooks/exhaustive-deps rule enabled on apps/client/hooks/useActiveConversation.ts
  2. Or verify via React documentation on exhaustive-deps rule: "When a value referenced inside these hooks isn't included in the dependency array, React won't re-run the effect or recalculate the value when that dependency changes."

Result: The effect does not re-run when contextConversationId changes independently of userId and params.conversationId. This means Priority 2 check (which determines if an existing conversation ID is available in the global context) may not execute at the appropriate time when the context is updated by other components.

Expected: Per React Rules of Hooks, all values used inside effects must be listed in the dependency array to ensure proper synchronization.

Fix applied: Added contextConversationId to the dependency array: [userId, params.conversationId, contextConversationId]. This is safe because:

  • The provider uses useState which prevents re-renders on identical values
  • Test suite (10 pass, 1 fail baseline) shows no new failures after the fix
  • The fix ensures the effect re-runs when the global context value changes
Fix on Vercel

- Add contextConversationId to useEffect dependency array in useActiveConversation
- Fix timeout error message check from 8 seconds to 15 seconds in conversations service
- Add .catch() handler to handlePress call to prevent unhandled promise rejections
- Ensures navigation errors are properly caught and logged
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.

Infinite chats creation when you navigate back-forth to modals

2 participants