Skip to content

Detail-page tab strip resets to "Details" on any URL search-param change (uncontrolled PageTabsRenderer) — make tab state URL-driven (ADR-0054 C3) #2257

Description

@os-zhuang

现象(浏览器实测,showcase account 详情页)

在记录详情页切到任意非默认 tab(如 Related / Invoices),然后发生任何 URL search 参数变化 —— tab 条立即重置回 Details,滚动位置同弃。触发源包括:

即:这是既有缺陷,#2256 只是让它更容易被撞上(其"子表保存后父详情 tab 保留"的验收项因此打了折扣——父路由/数据确实原地不动,但 tab 回到了 Details)。

根因

tab 条是非受控 Radix Tabs:

  • schema 路径:packages/components/src/renderers/layout/containers.tsx PageTabsRenderer — <Tabs defaultValue={itemsWithValue[0]?.value}>;
  • legacy 路径:packages/plugin-detail/src/DetailView.tsx autoTabs 分支 — <Tabs defaultValue="details">。

active tab 只活在组件实例里;URL 变化 → 上层子树重挂载 → 状态清零。

建议修复(ADR-0054 C3:URL-addressable state)

把详情页 tab 状态放进 URL(如 ?tab=<value>,replace 写入不压 history):

  1. PageTabsRenderer 支持受控 value + onValueChange(components 包不依赖 router,由宿主注入);
  2. app-shell RecordDetailView 从 searchParams 读/写 tab,经 page schema(或 RecordContext)传入;
  3. autoTabs legacy 分支同样接 schema.defaultTab / onTabChange;
  4. 顺带收益:tab 可深链、刷新保留、Back/Forward 可用 —— 与 ?recordId=/?form= 同一契约family。

验收

Refs framework#2604 · #2256(其 PR 描述"已知边界"节)

Activity

  1. os-zhuang commented on Jul 5, 2026

    @os-zhuang
    ContributorAuthor

    根因诊断补充(mount 探针 + StrictMode A/B 对照,浏览器实测):

    "任何 URL 参数变化都重挂载"是 dev-only(StrictMode)伪影——同一操作序列(Related tab → 打开 ?form= overlay → Esc):

    • StrictMode OFF:RecordDetailView / SchemaRenderer(page:tabs) / PageTabsRenderer 三层探针零 UNMOUNT,tab 保留;
    • StrictMode ON:打开 overlay 瞬间 RecordDetailView 整树 UNMOUNT→REMOUNT(连环两轮),tab 重置。

    因此生产用户不受 ?recordId= / ?form= / 命令面板这类 URL 变化影响;但生产真实存在的触发面仍有两个:AppContent 的 <RecordDetailView key={refreshKey}>(顶层编辑保存后 bump)和 RecordDetailView 的 <DetailView key={actionRefreshKey}>(记录 action 执行后 bump)——这两条在生产也会整树重建、丢 tab。

    修复(#2267)按原方案 URL 化(?tab=,ADR-0054 C3):状态搬出组件后对上述两类触发全部免疫,并顺带获得深链/刷新保留。dev 体验(StrictMode 下的 URL churn)同样修复。StrictMode 下 URL 变化为何重挂载 RecordDetailView(疑与 lazy + Suspense + router transition 的组合有关)可另行深挖,但已不阻塞本 issue。


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions