diff --git a/client/src/hooks/Conversations/index.ts b/client/src/hooks/Conversations/index.ts index 6c35ad5da..3507047c6 100644 --- a/client/src/hooks/Conversations/index.ts +++ b/client/src/hooks/Conversations/index.ts @@ -3,6 +3,7 @@ export { default as useGetSender } from './useGetSender'; export { default as useDefaultConvo } from './useDefaultConvo'; export { default as useSearchEnabled } from './useSearchEnabled'; export { default as useGenerateConvo } from './useGenerateConvo'; +export { default as useBackToNewChat } from './useBackToNewChat'; export { default as useDebouncedInput } from './useDebouncedInput'; export { default as useBookmarkSuccess } from './useBookmarkSuccess'; export { default as useNavigateToConvo } from './useNavigateToConvo'; diff --git a/client/src/hooks/Conversations/useBackToNewChat.ts b/client/src/hooks/Conversations/useBackToNewChat.ts new file mode 100644 index 000000000..6e126ef27 --- /dev/null +++ b/client/src/hooks/Conversations/useBackToNewChat.ts @@ -0,0 +1,40 @@ +import { useEffect } from 'react'; +import { useQueryClient } from '@tanstack/react-query'; +import { QueryKeys, Constants } from 'librechat-data-provider'; +import type { TMessage } from 'librechat-data-provider'; +import { useNewConvo } from '~/hooks'; +import { logger } from '~/utils'; +import store from '~/store'; + +/** + * Hook to detect and handle back navigation to /c/new + * This solves the issue where navigating back to new chat doesn't properly reset state + */ +export default function useBackToNewChat(index = 0) { + const queryClient = useQueryClient(); + const { newConversation } = useNewConvo(index); + const { conversation } = store.useCreateConversationAtom(index); + + // Listen for popstate events (back/forward button navigation) + useEffect(() => { + const handlePopState = () => { + const currentPath = window.location.pathname; + if (currentPath === '/c/new' && conversation?.conversationId !== Constants.NEW_CONVO) { + logger.log('conversation', 'Back navigation to /c/new detected, resetting state'); + + // Clear messages + queryClient.setQueryData( + [QueryKeys.messages, conversation?.conversationId ?? Constants.NEW_CONVO], + [], + ); + queryClient.invalidateQueries([QueryKeys.messages]); + + // Reset conversation + newConversation(); + } + }; + + window.addEventListener('popstate', handlePopState); + return () => window.removeEventListener('popstate', handlePopState); + }, [conversation?.conversationId, queryClient, newConversation]); +} diff --git a/client/src/routes/ChatRoute.tsx b/client/src/routes/ChatRoute.tsx index d81cbc075..d5437b4a5 100644 --- a/client/src/routes/ChatRoute.tsx +++ b/client/src/routes/ChatRoute.tsx @@ -5,7 +5,13 @@ import { Constants, EModelEndpoint } from 'librechat-data-provider'; import { useGetModelsQuery } from 'librechat-data-provider/react-query'; import type { TPreset } from 'librechat-data-provider'; import { useGetConvoIdQuery, useGetStartupConfig, useGetEndpointsQuery } from '~/data-provider'; -import { useNewConvo, useAppStartup, useAssistantListMap, useIdChangeEffect } from '~/hooks'; +import { + useNewConvo, + useAppStartup, + useBackToNewChat, + useIdChangeEffect, + useAssistantListMap, +} from '~/hooks'; import { getDefaultModelSpec, getModelSpecPreset, logger } from '~/utils'; import { ToolCallsMapProvider } from '~/Providers'; import ChatView from '~/components/Chat/ChatView'; @@ -32,6 +38,7 @@ export default function ChatRoute() { useIdChangeEffect(conversationId); const { hasSetConversation, conversation } = store.useCreateConversationAtom(index); const { newConversation } = useNewConvo(); + useBackToNewChat(index); const modelsQuery = useGetModelsQuery({ enabled: isAuthenticated, diff --git a/docs/fixes/back-button-navigation-fix.md b/docs/fixes/back-button-navigation-fix.md new file mode 100644 index 000000000..4037b8286 --- /dev/null +++ b/docs/fixes/back-button-navigation-fix.md @@ -0,0 +1,43 @@ +# Back Button Navigation Fix for LibreChat + +## Problem +When users navigate back to `/c/new` using the browser's back button from an existing conversation, the conversation state doesn't reset properly. This causes new messages to be appended to the previous conversation instead of creating a new one. + +## Solution +Created a custom hook `useBackToNewChat` that listens for browser back/forward navigation events and resets the conversation state when navigating back to `/c/new`. + +## Implementation + +### New Hook: `useBackToNewChat` +Located at: `client/src/hooks/useBackToNewChat.ts` + +The hook: +1. **Listens to popstate events** - Detects when users use browser back/forward buttons +2. **Checks current path** - Verifies if the navigation landed on `/c/new` +3. **Resets conversation state** - Clears messages and creates a new conversation if needed + +### Integration +The hook is used in `ChatRoute.tsx`: +```typescript +// Handle back navigation to /c/new +useBackToNewChat(index); +``` + +## Why This Approach? +- **Direct browser event handling** - The `popstate` event fires specifically for browser navigation (back/forward buttons) +- **No complex state tracking** - Avoids finicky effects that depend on conversation state changes +- **Simple and focused** - Single responsibility: detect back navigation to new chat and reset state + +## Benefits +- Minimal impact on existing code +- Isolated logic that's easier to test and maintain +- Directly addresses the root cause (browser back button) +- Avoids race conditions with conversation state updates + +## Testing +Test file: `client/src/hooks/__tests__/useBackToNewChat.test.ts` + +Tests cover: +- Popstate event handling when navigating to /c/new +- No action when already on /c/new +- No action when navigating to other routes \ No newline at end of file