diff --git a/source/src/components/DataSource/getDataSourceApi.ts b/source/src/components/DataSource/getDataSourceApi.ts index ff0d3447..0690c9cc 100644 --- a/source/src/components/DataSource/getDataSourceApi.ts +++ b/source/src/components/DataSource/getDataSourceApi.ts @@ -50,6 +50,10 @@ class DataSourceApiImpl implements DataSourceApi { private getState: () => DataSourceState; private actions: DataSourceComponentActions; + //@ts-ignore + private batchOperationRafId: number = 0; + //@ts-ignore + private batchOperationTimeoutId: any = 0; constructor(param: GetDataSourceApiParam) { this.getState = param.getState; @@ -68,9 +72,20 @@ class DataSourceApiImpl implements DataSourceApi { this.pendingPromise = new Promise((resolve) => { this.resolvePendingPromise = resolve; }); - raf(() => { - this.commit(); - }); + + const delay = Math.max(0, this.getState().batchOperationDelay ?? 0); + + if (delay === 0) { + this.batchOperationRafId = raf(() => { + this.commit(); + }); + } else { + this.batchOperationTimeoutId = setTimeout(() => { + this.batchOperationRafId = raf(() => { + this.commit(); + }); + }, delay); + } } this.pendingOperations.push(operation); diff --git a/source/src/components/DataSource/state/getInitialState.ts b/source/src/components/DataSource/state/getInitialState.ts index f30bdabd..eb0cabe1 100644 --- a/source/src/components/DataSource/state/getInitialState.ts +++ b/source/src/components/DataSource/state/getInitialState.ts @@ -200,6 +200,7 @@ export const forwardProps = ( __idToIndex: idToIndexReducer, }; }, + batchOperationDelay: 1, isRowSelected: 1, onDataArrayChange: 1, onDataMutations: 1, diff --git a/source/src/components/DataSource/types.ts b/source/src/components/DataSource/types.ts index ce9de6d5..e83be8f3 100644 --- a/source/src/components/DataSource/types.ts +++ b/source/src/components/DataSource/types.ts @@ -133,6 +133,8 @@ export interface DataSourceMappedState { isRowSelected: DataSourceProps['isRowSelected']; debugId: DataSourceProps['debugId']; + batchOperationDelay: DataSourceProps['batchOperationDelay']; + onDataArrayChange: DataSourceProps['onDataArrayChange']; onDataMutations: DataSourceProps['onDataMutations']; onReady: DataSourceProps['onReady']; @@ -481,6 +483,8 @@ export type DataSourceProps = { fields?: (keyof T)[]; refetchKey?: number | string | object; + batchOperationDelay?: number; + rowInfoReducers?: DataSourcePropRowInfoReducers; // TODO move this on the DataSourceAPI? I think so diff --git a/source/src/components/InfiniteTable/components/InfiniteTableRow/InfiniteTableCell.tsx b/source/src/components/InfiniteTable/components/InfiniteTableRow/InfiniteTableCell.tsx index 7812b151..e6de5468 100644 --- a/source/src/components/InfiniteTable/components/InfiniteTableRow/InfiniteTableCell.tsx +++ b/source/src/components/InfiniteTable/components/InfiniteTableRow/InfiniteTableCell.tsx @@ -105,7 +105,7 @@ function InfiniteTableCellFn( ? column.components?.ColumnCell : column.components?.HeaderCell; if (RenderComponent) { - return ; + return ; } return
; } diff --git a/source/src/components/hooks/useComponentState/index.tsx b/source/src/components/hooks/useComponentState/index.tsx index 3215fb98..4456935d 100644 --- a/source/src/components/hooks/useComponentState/index.tsx +++ b/source/src/components/hooks/useComponentState/index.tsx @@ -292,6 +292,7 @@ export function buildManagedComponent< T_PARENT_STATE >, ) { + const useParentStateFn = config.getParentState || (() => null); /** * since config is passed outside the cmp, we can skip it inside useMemo deps list */ @@ -319,7 +320,7 @@ export function buildManagedComponent< COMPONENT_DERIVED_STATE & COMPONENT_SETUP_STATE; - const parentState = config.getParentState?.() ?? null; + const parentState = useParentStateFn(); const getParentState = useLatest(parentState); function initStateOnce() { @@ -382,6 +383,7 @@ export function buildManagedComponent< } const parentState = getParentState?.() ?? null; + const mappedState: Partial | null = action.payload.mappedState; const updatedProps: Partial | null = @@ -500,6 +502,9 @@ export function buildManagedComponent< const prevProps = usePrevious(props); + const skipTriggerParentStateChangeRef = useRef(false); + skipTriggerParentStateChangeRef.current = false; + const effectFn = config.layoutEffect ? useLayoutEffect : useEffect; effectFn(() => { const currentProps = props; @@ -582,6 +587,7 @@ export function buildManagedComponent< // const newState = theReducer(state, action); + skipTriggerParentStateChangeRef.current = true; dispatch(action); if (config.onPropChange) { @@ -612,6 +618,15 @@ export function buildManagedComponent< } }); + effectFn(() => { + if (parentState != null && !skipTriggerParentStateChangeRef.current) { + dispatch({ + type: 'PARENT_STATE_CHANGE', + payload: {}, + }); + } + }, [parentState]); + useEffectOnce(() => { return () => { config.cleanup?.(getComponentState());