fix(inbox): parse issue query param on initial page load

Use useState for selectedKey instead of deriving directly from
useSearchParams(), so the issue ID from ?issue=<id> is reliably
captured on mount. window.history.replaceState() doesn't always
sync back to useSearchParams() in Next.js, causing the detail
panel to show empty when entering via a shared inbox link.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Naiyuan Qing 2026-04-02 18:51:14 +08:00
parent fdba410f11
commit c3cca50f27

View file

@ -1,5 +1,6 @@
"use client";
import { useState, useEffect, useCallback } from "react";
import { useSearchParams } from "next/navigation";
import { useDefaultLayout } from "react-resizable-panels";
import { useInboxStore } from "@/features/inbox";
@ -219,11 +220,20 @@ function InboxListItem({
export default function InboxPage() {
const searchParams = useSearchParams();
const selectedKey = searchParams.get("issue") ?? "";
const setSelectedKey = (key: string) => {
const urlIssue = searchParams.get("issue") ?? "";
const [selectedKey, setSelectedKeyState] = useState(() => urlIssue);
// Sync from URL when searchParams change (e.g. Next.js navigation)
useEffect(() => {
setSelectedKeyState(urlIssue);
}, [urlIssue]);
const setSelectedKey = useCallback((key: string) => {
setSelectedKeyState(key);
const url = key ? `/inbox?issue=${key}` : "/inbox";
window.history.replaceState(null, "", url);
};
}, []);
const items = useInboxStore((s) => s.dedupedItems());
const loading = useInboxStore((s) => s.loading);