Skip to content

fix(web): re-add handleChangeConversation to handleNewConversation deps (#38403)#38573

Open
Taranum01 wants to merge 1 commit into
langgenius:mainfrom
Taranum01:fix/38403-embedded-chatbot-reset-stale-deps
Open

fix(web): re-add handleChangeConversation to handleNewConversation deps (#38403)#38573
Taranum01 wants to merge 1 commit into
langgenius:mainfrom
Taranum01:fix/38403-embedded-chatbot-reset-stale-deps

Conversation

@Taranum01

Copy link
Copy Markdown

Fixes #38403

Problem

Since PR #31287 ("feat: frontend part of support try apps"), the embedded chatbot's handleNewConversation (web/app/components/base/chat/embedded-chatbot/hooks.tsx) was missing handleChangeConversation from its useCallback deps array.

-  }, [handleChangeConversation, setShowNewConversationItemInList, handleNewConversationInputsChange, setClearChatList])
+  }, [isTryApp, setShowNewConversationItemInList, handleNewConversationInputsChange, setClearChatList])

After URL→localStorage resolution or any state change that touched handleConversationIdInfoChange's deps (appId, conversationIdInfo, userId), handleChangeConversation regenerates but handleNewConversation keeps the previous render's closure. Clicking reset then calls handleChangeConversation('') against a stale handleConversationIdInfoChange that closes over the previous conversationIdInfo. The setConversationIdInfo({ ...conversationIdInfo, ... }) write hits the discarded snapshot rather than the live state, so conversationIdInfo[appId][userId] is never reset. The next message re-uses the old conversation_id.

Fix

Re-add handleChangeConversation to handleNewConversation's deps array. This restores the v1.6.0 deps (pre-#31287) and keeps the two callbacks in lockstep:

-  }, [isTryApp, setShowNewConversationItemInList, handleNewConversationInputsChange, setClearChatList])
+  }, [isTryApp, setShowNewConversationItemInList, handleChangeConversation, handleNewConversationInputsChange, setClearChatList])

react/exhaustive-deps is now satisfied on line 371. useCallback only re-emits when a dep reference changes; at steady state (no state mutation across renders) both callbacks short-circuit and preserve identity, so the rerender cost is unchanged.

Test

Added a regression test in web/app/components/base/chat/embedded-chatbot/__tests__/hooks.spec.tsx that:

  1. Stores a conversation_id in localStorage and disables URL/system-variable resolution so the path under test is the localStorage branch.
  2. Captures the initial handleNewConversation and handleChangeConversation references.
  3. A no-prop rerender preserves both references (validates useCallback memoization at steady state).
  4. Flips mockStoreState.embeddedUserId to force the line-75 effect → userId state → handleConversationIdInfoChange deps → handleChangeConversation to regenerate.
  5. Asserts handleNewConversation regenerates alongside handleChangeConversation — without the fix this assertion fails (Object.is equality on the stale closure).

Run with:

pnpm exec vitest run app/components/base/chat/embedded-chatbot/__tests__/hooks.spec.tsx

Verification

  • pnpm exec vitest run on the touched spec: 36/36 pass
  • pnpm exec vitest run on app/components/base/chat/ (1355 tests across 73 files): all pass
  • pnpm exec eslint --fix --pass-on-unpruned-suppressions on the two changed files: 0 errors, 4 pre-existing exhaustive-deps warnings on unrelated useEffect blocks (lines 74, 105, 250, 311) — none introduced by this change
  • pnpm exec tsgo --noEmit: clean
  • Confirmed the new test fails on the unpatched code (reverted the 1-line deps change → test failed with expected [AsyncFunction] not to be [AsyncFunction]), then restored the fix and re-ran → test passes

Risk

Minimal. Pure deps-array change. No public-API change, no schema/migration/controller/frontend logic outside the touched file. The change only affects callers of handleNewConversation (the embedded chatbot reset button) — and only positively: they now reach the freshest handleChangeConversation instead of a stale one.

Reverts the same useCallback deps edit as PR #31287 did back when it introduced the Try Apps branch. If PR #31287 needed a smaller-deps form for performance reasons, please call that out in review and we can revisit (the call to handleChangeConversation('')['] only happens once per reset click so the cost change is negligible).

Made with Cursor

Resolves a stale closure in the embedded chatbot reset path. Since
PR langgenius#31287 (Try Apps refactor), handleNewConversation in
web/app/components/base/chat/embedded-chatbot/hooks.tsx omitted
handleChangeConversation from its useCallback deps, so the reset
button captured the closure from the previous render. When
userId, appId, or conversationIdInfo changed between renders
(normal during URL→localStorage resolution), the reset click
called handleChangeConversation('') over a stale
handleConversationIdInfoChange — clearing the stored id in a
discarded snapshot rather than the live conversationIdInfo.
Subsequent messages re-used the previous conversation_id.

The original deps array (pre-PR langgenius#31287, v1.6.0) listed
handleChangeConversation. Restoring it puts the deps array back
in sync with handleChangeConversation's own deps and eliminates
the stale-closure window.

Adds a regression test in
web/app/components/base/chat/embedded-chatbot/__tests__/hooks.spec.tsx
that exercises the identity propagation through a forced
embeddedUserId mutation. Test fails on the broken deps array and
passes with the fix.

Fixes langgenius#38403
@dosubot dosubot Bot added the size:XS This PR changes 0-9 lines, ignoring generated files. label Jul 8, 2026
@github-actions github-actions Bot added the web This relates to changes on the web. label Jul 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XS This PR changes 0-9 lines, ignoring generated files. web This relates to changes on the web.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Possible regression since v1.13.0: embedded chatbot reset keeps using old conversation_id

1 participant