diff --git a/src/components/profile/proxies-editor-viewer.tsx b/src/components/profile/proxies-editor-viewer.tsx index a74f2c282..0c5d4b58c 100644 --- a/src/components/profile/proxies-editor-viewer.tsx +++ b/src/components/profile/proxies-editor-viewer.tsx @@ -73,16 +73,25 @@ export const ProxiesEditorViewer = (props: Props) => { const [appendSeq, setAppendSeq] = useState([]) const [deleteSeq, setDeleteSeq] = useState([]) + // 节点的 name 会被用作 SortableContext 的 item id、React key 以及拖拽排序的 + // 依据。当 name 为空/null(例如高级模式下粘贴了缺少 name 的节点)时, + // @dnd-kit 的 SortableContext 会对 null 执行 `'id' in item` 从而崩溃 + // (Cannot use 'in' operator to search for 'id' in null)。 + // 这里统一过滤掉没有有效 name 的节点,避免可视化编辑页崩溃;原始 YAML + // 数据仍然保留,用户可在高级(文本)模式中查看并修正这些节点。 + const hasValidName = (proxy: IProxyConfig) => + typeof proxy?.name === 'string' && proxy.name.length > 0 const filteredPrependSeq = useMemo( - () => prependSeq.filter((proxy) => match(proxy.name)), + () => + prependSeq.filter((proxy) => hasValidName(proxy) && match(proxy.name)), [prependSeq, match], ) const filteredProxyList = useMemo( - () => proxyList.filter((proxy) => match(proxy.name)), + () => proxyList.filter((proxy) => hasValidName(proxy) && match(proxy.name)), [proxyList, match], ) const filteredAppendSeq = useMemo( - () => appendSeq.filter((proxy) => match(proxy.name)), + () => appendSeq.filter((proxy) => hasValidName(proxy) && match(proxy.name)), [appendSeq, match], )