diff --git a/packages/core/client/src/schema-component/antd/association-field/SubTable.tsx b/packages/core/client/src/schema-component/antd/association-field/SubTable.tsx
index e1b302f4a..199eabe8c 100644
--- a/packages/core/client/src/schema-component/antd/association-field/SubTable.tsx
+++ b/packages/core/client/src/schema-component/antd/association-field/SubTable.tsx
@@ -91,7 +91,7 @@ export const SubTable: any = observer(
onClick={() => {
field.value = field.value || [];
field.value.push({});
- void field.onInput(field.value);
+ field.onInput(field.value);
}}
icon={}
>
diff --git a/packages/core/client/src/schema-component/antd/form-item/hooks/useParseDefaultValue.ts b/packages/core/client/src/schema-component/antd/form-item/hooks/useParseDefaultValue.ts
index 07206a546..95887953d 100644
--- a/packages/core/client/src/schema-component/antd/form-item/hooks/useParseDefaultValue.ts
+++ b/packages/core/client/src/schema-component/antd/form-item/hooks/useParseDefaultValue.ts
@@ -72,9 +72,8 @@ const useParseDefaultValue = () => {
setDefaultValue(value);
}
} else {
- // TODO: 可能会因为异步时序问题导致设置默认值无效
// eslint-disable-next-line promise/catch-or-return
- void Promise.resolve().then(() => {
+ Promise.resolve().then(() => {
field.setInitialValue(value);
});
}
@@ -91,7 +90,7 @@ const useParseDefaultValue = () => {
// 使用防抖,提高性能和用户体验
const run = _.debounce(_run, DEBOUNCE_WAIT);
- void _run();
+ _run();
if (isVariable(fieldSchema.default)) {
const variableName = getVariableName(fieldSchema.default);
diff --git a/packages/core/client/src/schema-component/antd/form-item/hooks/useSpecialCase.ts b/packages/core/client/src/schema-component/antd/form-item/hooks/useSpecialCase.ts
index 8998d1497..b1a83307b 100644
--- a/packages/core/client/src/schema-component/antd/form-item/hooks/useSpecialCase.ts
+++ b/packages/core/client/src/schema-component/antd/form-item/hooks/useSpecialCase.ts
@@ -162,13 +162,14 @@ export function isFromDatabase(value: Record) {
export const useSubTableSpecialCase = ({ field }) => {
useEffect(() => {
if (_.isEmpty(field.value)) {
+ const value = field.value;
field.value = [{}];
// 因为默认值的解析是异步的,所以下面的代码会优先于默认值的设置,这样就防止了设置完默认值后又被清空的问题
- Promise.resolve()
- .then(() => {
- field.value = [];
- })
- .catch(console.error);
+ setTimeout(() => {
+ if (JSON.stringify(field.value) === '[{}]') {
+ field.value = value;
+ }
+ });
}
}, []);
};
diff --git a/packages/core/client/src/schema-component/antd/table-v2/Table.tsx b/packages/core/client/src/schema-component/antd/table-v2/Table.tsx
index c6ee9db30..ed41f61c6 100644
--- a/packages/core/client/src/schema-component/antd/table-v2/Table.tsx
+++ b/packages/core/client/src/schema-component/antd/table-v2/Table.tsx
@@ -6,11 +6,12 @@ import { ArrayField } from '@formily/core';
import { spliceArrayState } from '@formily/core/esm/shared/internals';
import { RecursionField, Schema, observer, useField, useFieldSchema } from '@formily/react';
import { action } from '@formily/reactive';
+import { uid } from '@formily/shared';
import { isPortalInBody } from '@nocobase/utils/client';
import { useMemoizedFn } from 'ahooks';
import { Table as AntdTable, TableColumnProps } from 'antd';
import { default as classNames, default as cls } from 'classnames';
-import React, { useCallback, useEffect, useMemo, useState } from 'react';
+import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { DndContext, useDesignable, useTableSize } from '../..';
import {
@@ -101,12 +102,13 @@ const useTableColumns = (props: { showDel?: boolean; isSubTable?: boolean }) =>
{
- void action(() => {
+ action(() => {
spliceArrayState(field as any, {
startIndex: index,
deleteCount: 1,
});
field.value.splice(index, 1);
+ field.initialValue?.splice(index, 1);
return field.onInput(field.value);
});
}}
@@ -231,6 +233,7 @@ export const Table: any = observer(
const [selectedRow, setSelectedRow] = useState([]);
const dataSource = field?.value?.slice?.()?.filter?.(Boolean) || [];
const isRowSelect = rowSelection?.type !== 'none';
+ const defaultRowKeyMap = useRef(new Map());
let onRow = null,
highlightRow = '';
@@ -339,8 +342,29 @@ export const Table: any = observer(
};
}, [field, onRowDragEnd, dragSort]);
+ /**
+ * 为没有设置 key 属性的 record 生成一个唯一的 key
+ * 1. rowKey 的默认值是 “key”,所以先判断有没有 record.key;
+ * 2. 如果没有就生成一个唯一的 key,并以 record 的值作为索引;
+ * 3. 这样下次就能取到对应的 key 的值;
+ *
+ * 这里有效的前提是:数组中对应的 record 的引用不会发生改变。
+ *
+ * @param record
+ * @returns
+ */
const defaultRowKey = (record: any) => {
- return field.value?.indexOf?.(record);
+ if (record.key) {
+ return record.key;
+ }
+
+ if (defaultRowKeyMap.current.has(record)) {
+ return defaultRowKeyMap.current.get(record);
+ }
+
+ const key = uid();
+ defaultRowKeyMap.current.set(record, key);
+ return key;
};
const getRowKey = (record: any) => {
diff --git a/packages/core/client/src/variables/constants.ts b/packages/core/client/src/variables/constants.ts
index efca9325c..ed01ddb99 100644
--- a/packages/core/client/src/variables/constants.ts
+++ b/packages/core/client/src/variables/constants.ts
@@ -1 +1 @@
-export const DEBOUNCE_WAIT = 500;
+export const DEBOUNCE_WAIT = 300;