Skip to content

Problem 1:新条目插入顺序与连通性状态的冲突

记录于 PR #289 review 阶段,gemini-code-assist 指出的问题

问题描述

PR1 有两个目标,但它们存在冲突:

目标做法冲突点
新条目出现在顶部(UX)prepend: [new, ...old]数组下标整体后移
连通性状态不丢失openaiStatuses[idx] 按下标追踪下标变了,状态就错位了

根因:useConnectivityTest.ts 用数组下标绑定状态,而 key={idx} 也按下标识别 DOM 节点。prepend 导致所有已有条目的下标 +1,两套机制同时失效。

具体表现

插入前(3 个条目):

下标条目签名连通性状态
0AA_sigsuccess
1BB_sigloading
2CC_sigerror

prepend 新条目后(4 个条目):

下标条目curr[i]prev[i]匹配?状态结果
0newnew_sigA_sigidle(本来就是)
1AA_sigB_sig被重置为 idle(丢失 success)
2BB_sigC_sig被重置为 idle(丢失 loading)
3CC_sigundefined跳过error 保留

所有已有条目的连通性测试状态均丢失。

相关代码

  • 状态同步逻辑:src/features/providers/sheets/forms/useConnectivityTest.ts:140-158
  • 渲染 key:BaseProviderForm.tsxkey={idx}
  • 状态读取:connectivity.openaiStatuses[idx]

解决思路

数组顺序和显示顺序是两件事,分离开:

数组(状态层):始终 append   →  [A, B, C, new]
                                    下标稳定
显示(视图层):渲染时 reverse →  [new, C, B, A]
                                    用户看到新条目在顶部
  • 数组操作:[...apiKeyEntries, emptyApiKeyEntry()] — 追加,下标不变
  • 渲染:[...apiKeyEntries].reverse().map(...) — 倒序,新条目视觉在前
  • 连通性查找:openaiStatuses[realIdx] — 用真实下标,状态不丢失
  • React key:key={realIdx} — DOM 节点识别正确,无 focus 问题

具体改动(仅 BaseProviderForm.tsx)

tsx
// 按钮:追加,不 prepend
onClick={() =>
  updateField('apiKeyEntries', [...apiKeyEntries, emptyApiKeyEntry()])
}

// 渲染:倒序,用 realIdx 关联状态和 key
{[...apiKeyEntries].reverse().map((entry, visualIdx) => {
  const realIdx = apiKeyEntries.length - 1 - visualIdx;
  const status = connectivity.openaiStatuses[realIdx] ?? {
    state: 'idle' as ConnectivityState,
    message: '',
  };
  return (
    <div key={realIdx} className={styles.entryCard}>
      {/* 删除按钮也用 realIdx */}
      onClick={() =>
        updateField(
          'apiKeyEntries',
          apiKeyEntries.filter((_, i) => i !== realIdx)
        )
      }
      ...
    </div>
  );
})}

变更范围总结

层面是否改动
状态管理(useConnectivityTest)不动
数据结构(ApiKeyEntryInput)不动
数组操作(updateField)改回 append,与原代码一致
渲染顺序.reverse() + realIdx 映射

改动最小,两层关注点完全解耦。