From f091ac322b252e803b63ebfdbc8766dea59847b2 Mon Sep 17 00:00:00 2001 From: Menghuan1918 Date: Sat, 8 Aug 2026 23:51:42 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20sidebar=20crash=20#310=20=E2=80=94=20ref?= =?UTF-8?q?erenceInChat=20hook=20sat=20behind=20the=20no-session=20early?= =?UTF-8?q?=20return?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The new useCallback was declared after the early return for the no-session state, so the first render (no session) ran fewer hooks than the follow-up render once a session arrived — React error #310, boundary strip on load. Moved the hook above the early return (with a sessionId guard) and verified headlessly: the error no longer appears and the panel renders fully. --- src/client/Sidebar.tsx | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/src/client/Sidebar.tsx b/src/client/Sidebar.tsx index a00a301..8f41251 100644 --- a/src/client/Sidebar.tsx +++ b/src/client/Sidebar.tsx @@ -185,6 +185,28 @@ export function Sidebar(props: { ctx: Context }) { }, }), [sessionId, cwd]) + /** + * The explorer's @-reference button: append `@` to the + * session's composer draft (space-separated). Resolves the session-scope + * ctx and the conversation input service at click time; a missing service + * or scope degrades to a logged no-op, never a crash. Defined above the + * no-session early return — a hook must never sit behind a conditional + * return (React counts hooks per render). + */ + const referenceInChat = useCallback((path: string): void => { + if (sessionId === undefined) return + try { + const actx = ctx.sessions.scope(sessionId) + if (actx === undefined) return + const input = ctx.conversation.input.for(actx) + const mention = `@${relativeTo(cwd ?? '', path)}` + const draft = input.state.getSnapshot().draft + input.setDraft(draft.trim() === '' ? mention : `${draft} ${mention}`) + } catch (error) { + console.warn('[dsh-better-sidebar] reference insert failed:', error) + } + }, [ctx, sessionId, cwd]) + if (state === undefined || sessionId === undefined) { return (
@@ -225,19 +247,6 @@ export function Sidebar(props: { ctx: Context }) { * ctx and the conversation input service at click time; a missing service * or scope degrades to a logged no-op, never a crash. */ - const referenceInChat = useCallback((path: string): void => { - try { - const actx = ctx.sessions.scope(sessionId) - if (actx === undefined) return - const input = ctx.conversation.input.for(actx) - const mention = `@${relativeTo(cwd ?? '', path)}` - const draft = input.state.getSnapshot().draft - input.setDraft(draft.trim() === '' ? mention : `${draft} ${mention}`) - } catch (error) { - console.warn('[dsh-better-sidebar] reference insert failed:', error) - } - }, [ctx, sessionId, cwd]) - const renderTab = (tab: SidebarTab) => (