From b0dc133b4f1631f8f9202ce02d214800f3a07eb0 Mon Sep 17 00:00:00 2001 From: nevermore Date: Mon, 20 May 2024 16:08:42 +0800 Subject: [PATCH 1/3] Fix:#6141:DataTable:Column: onCellEditComplete is fired twice --- components/lib/datatable/BodyCell.js | 53 ++++++++++++++-------------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/components/lib/datatable/BodyCell.js b/components/lib/datatable/BodyCell.js index f6d95fb5fb..93a63f524f 100644 --- a/components/lib/datatable/BodyCell.js +++ b/components/lib/datatable/BodyCell.js @@ -1,7 +1,7 @@ import * as React from 'react'; import { ariaLabel } from '../api/Api'; import { ColumnBase } from '../column/ColumnBase'; -import { useEventListener, useMergeProps, useUnmountEffect, useUpdateEffect } from '../hooks/Hooks'; +import { useEventListener, useMergeProps, usePrevious, useUnmountEffect, useUpdateEffect } from '../hooks/Hooks'; import { BarsIcon } from '../icons/bars'; import { CheckIcon } from '../icons/check'; import { ChevronDownIcon } from '../icons/chevrondown'; @@ -25,6 +25,7 @@ export const BodyCell = React.memo((props) => { const selfClick = React.useRef(false); const tabindexTimeout = React.useRef(null); const initFocusTimeout = React.useRef(null); + const editingRowDataStateRef = React.useRef(null); const { ptm, ptmo, cx } = props.ptCallbacks; const getColumnProp = (name) => ColumnBase.getCProp(props.column, name); @@ -157,43 +158,41 @@ export const BodyCell = React.memo((props) => { unbindDocumentClickListener(); OverlayService.off('overlay-click', overlayEventListener.current); overlayEventListener.current = null; + editingRowDataStateRef.current = null; selfClick.current = false; }, 1); }; const switchCellToViewMode = (event, submit) => { const callbackParams = getCellCallbackParams(event); + const newRowData = { ...editingRowDataStateRef.current }; + const newValue = resolveFieldData(newRowData); + const params = { ...callbackParams, newRowData, newValue }; + const onCellEditCancel = getColumnProp('onCellEditCancel'); + const cellEditValidator = getColumnProp('cellEditValidator'); + const onCellEditComplete = getColumnProp('onCellEditComplete'); + + if (!submit && onCellEditCancel) { + onCellEditCancel(params); + } - setEditingRowDataState((prev) => { - const newRowData = prev; - const newValue = resolveFieldData(newRowData); - const params = { ...callbackParams, newRowData, newValue }; - const onCellEditCancel = getColumnProp('onCellEditCancel'); - const cellEditValidator = getColumnProp('cellEditValidator'); - const onCellEditComplete = getColumnProp('onCellEditComplete'); - - if (!submit && onCellEditCancel) { - onCellEditCancel(params); - } + let valid = true; - let valid = true; + if ((!submit || cellEditValidateOnClose()) && cellEditValidator) { + valid = cellEditValidator(params); + } - if ((!submit || cellEditValidateOnClose()) && cellEditValidator) { - valid = cellEditValidator(params); + if (valid) { + if (submit && onCellEditComplete) { + onCellEditComplete(params); } - if (valid) { - if (submit && onCellEditComplete) { - setTimeout(() => onCellEditComplete(params)); - } - - closeCell(event); - } else { - event.preventDefault(); - } + closeCell(event); + } else { + event.preventDefault(); + } - return newRowData; - }); + setEditingRowDataState(newRowData); }; const findNextSelectableCell = (cell) => { @@ -294,6 +293,8 @@ export const BodyCell = React.memo((props) => { if (currentData) { ObjectUtils.mutateFieldData(currentData, field, val); } + + editingRowDataStateRef.current = editingRowData; }; const onClick = (event) => { From c1f1d0cede04ab87e2dfb59a86fa4772b310993a Mon Sep 17 00:00:00 2001 From: nevermore Date: Mon, 20 May 2024 16:23:57 +0800 Subject: [PATCH 2/3] remove unused import --- components/lib/datatable/BodyCell.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/lib/datatable/BodyCell.js b/components/lib/datatable/BodyCell.js index 93a63f524f..e80ad8f27d 100644 --- a/components/lib/datatable/BodyCell.js +++ b/components/lib/datatable/BodyCell.js @@ -1,7 +1,7 @@ import * as React from 'react'; import { ariaLabel } from '../api/Api'; import { ColumnBase } from '../column/ColumnBase'; -import { useEventListener, useMergeProps, usePrevious, useUnmountEffect, useUpdateEffect } from '../hooks/Hooks'; +import { useEventListener, useMergeProps, useUnmountEffect, useUpdateEffect } from '../hooks/Hooks'; import { BarsIcon } from '../icons/bars'; import { CheckIcon } from '../icons/check'; import { ChevronDownIcon } from '../icons/chevrondown'; From eefd7deeef8fda17c79486b865ddedec7f990004 Mon Sep 17 00:00:00 2001 From: nevermore Date: Mon, 20 May 2024 19:53:51 +0800 Subject: [PATCH 3/3] feat: use React.useEffect sync editingRowData --- components/lib/datatable/BodyCell.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/components/lib/datatable/BodyCell.js b/components/lib/datatable/BodyCell.js index e80ad8f27d..9ab5617d47 100644 --- a/components/lib/datatable/BodyCell.js +++ b/components/lib/datatable/BodyCell.js @@ -293,8 +293,6 @@ export const BodyCell = React.memo((props) => { if (currentData) { ObjectUtils.mutateFieldData(currentData, field, val); } - - editingRowDataStateRef.current = editingRowData; }; const onClick = (event) => { @@ -524,6 +522,12 @@ export const BodyCell = React.memo((props) => { } }, [props.editingMeta]); + React.useEffect(() => { + if (editingRowDataState) { + editingRowDataStateRef.current = editingRowDataState; + } + }, [editingRowDataState]); + React.useEffect(() => { if (props.editMode === 'cell' || props.editMode === 'row') { const callbackParams = getCellCallbackParams();