fix: prevent duplicate conversation creation and improve chat state persistence#116
Conversation
- 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
There was a problem hiding this comment.
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:
- Run ESLint with
react-hooks/exhaustive-depsrule enabled onapps/client/hooks/useActiveConversation.ts - 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
useStatewhich 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
- 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
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:
Type of Change
Release
Is this a release? No - this is a bug fix. Maintainers will handle versioning when merging.
Testing
Tested scenarios:
Test environment:
Checklist