🐛 fix(data-grid): 修复刷新后未提交修改被清空

This commit is contained in:
Syngnat
2026-06-24 15:56:07 +08:00
parent 1cb112bcdf
commit d08ab62f92
3 changed files with 64 additions and 9 deletions

View File

@@ -1091,6 +1091,64 @@ describe('DataGrid DDL interactions', () => {
renderer!.unmount();
});
it('keeps pending local changes visible after refreshing the grid', async () => {
const reloadSpy = vi.fn();
const Harness = () => {
const [rows, setRows] = React.useState([
{ __gonavi_row_key__: 'row-1', id: 1, name: 'old' },
]);
return (
<DataGrid
data={rows}
columnNames={['id', 'name']}
loading={false}
tableName="users"
dbName="main"
connectionId="conn-1"
pkColumns={['id']}
editLocator={{
strategy: 'primary-key',
columns: ['id'],
valueColumns: ['id'],
readOnly: false,
}}
onReload={() => {
reloadSpy();
setRows([{ __gonavi_row_key__: 'row-1', id: 1, name: 'old' }]);
}}
/>
);
};
let renderer: ReactTestRenderer;
await act(async () => {
renderer = create(<Harness />);
});
await waitForEffects();
await act(async () => {
renderer!.root.findByType(DataGridToolbarFrame).props.onAddRow();
});
await waitForEffects();
expect(testRenderState.latestTableProps.dataSource).toHaveLength(2);
expect(renderer!.root.findByType(DataGridToolbarFrame).props.pendingChangeCount).toBe(1);
await act(async () => {
renderer!.root.findByType(DataGridToolbarFrame).props.onRefresh();
});
await waitForEffects();
await waitForEffects();
expect(reloadSpy).toHaveBeenCalledTimes(1);
expect(testRenderState.latestTableProps.dataSource).toHaveLength(2);
expect(testRenderState.latestTableProps.dataSource[1][GONAVI_ROW_KEY]).toContain('new-');
expect(renderer!.root.findByType(DataGridToolbarFrame).props.pendingChangeCount).toBe(1);
renderer!.unmount();
});
it('localizes v2 column header fallback labels', () => {
setCurrentLanguage('en-US');

View File

@@ -2037,10 +2037,13 @@ describe('DataGrid layout', () => {
}
});
it('clears modified cell markers when refreshing the grid', () => {
it('keeps pending cell markers when refreshing the grid', () => {
const source = readDataGridSource();
expect(source).toMatch(/const handleRefreshGrid = useCallback\(\(\) => \{[\s\S]*setModifiedColumns\(\{\}\);[\s\S]*if \(onReload\) onReload\(\);[\s\S]*\}, \[[\s\S]*clearAutoCommitTimer[\s\S]*onReload[\s\S]*\]\);/);
expect(source).toMatch(/const handleRefreshGrid = useCallback\(\(\) => \{[\s\S]*setSelectedRowKeys\(\[\]\);[\s\S]*if \(onReload\) onReload\(\);[\s\S]*\}, \[[\s\S]*onReload[\s\S]*\]\);/);
expect(source).not.toMatch(/const handleRefreshGrid = useCallback\(\(\) => \{[\s\S]*setAddedRows\(\[\]\);[\s\S]*if \(onReload\) onReload\(\);[\s\S]*\}\,/);
expect(source).not.toMatch(/const handleRefreshGrid = useCallback\(\(\) => \{[\s\S]*setModifiedRows\(\{\}\);[\s\S]*if \(onReload\) onReload\(\);[\s\S]*\}\,/);
expect(source).not.toMatch(/const handleRefreshGrid = useCallback\(\(\) => \{[\s\S]*setDeletedRowKeys\(new Set\(\)\);[\s\S]*if \(onReload\) onReload\(\);[\s\S]*\}\,/);
});
it('routes temporal inline editors through the current connection config', () => {

View File

@@ -479,12 +479,6 @@ const renderDataTableView = () => (
), [columnMetaMap, columnMetaMapByLowerName, currentConnConfig, dbType, displayColumnNames, effectiveEditLocator, rowEditorOpen, rowEditorRowKey]);
const handleRefreshGrid = useCallback(() => {
clearAutoCommitTimer();
autoCommitFailedTokenRef.current = -1;
setAddedRows([]);
setModifiedRows({});
setDeletedRowKeys(new Set());
setModifiedColumns({});
setSelectedRowKeys([]);
const normalizedTableName = String(tableName || '').trim();
const normalizedDbName = String(dbName || '').trim();
@@ -496,7 +490,7 @@ const renderDataTableView = () => (
setMetadataReloadVersion((value: number) => value + 1);
}
if (onReload) onReload();
}, [clearAutoCommitTimer, connectionId, dbName, onReload, tableName]);
}, [connectionId, dbName, onReload, tableName]);
const handleResetPendingChanges = useCallback(() => {
clearAutoCommitTimer();