diff --git a/src/Cell.tsx b/src/Cell.tsx index 7bf79e08..290a7280 100644 --- a/src/Cell.tsx +++ b/src/Cell.tsx @@ -57,15 +57,20 @@ export const Cell: React.FC = ({ [setCellDimensions, select, dragging, point] ); + const modeRef = React.useRef(); + React.useEffect(() => { + modeRef.current = mode; + }, [mode]); + React.useEffect(() => { const root = rootRef.current; if (selected && root) { setCellDimensions(point, getOffsetRect(root)); } - if (root && active && mode === "view") { + if (root && active && modeRef.current === "view") { root.focus(); } - }, [setCellDimensions, selected, active, mode, point, data]); + }, [setCellDimensions, selected, active, point, data]); if (data && data.DataViewer) { // @ts-ignore diff --git a/src/Spreadsheet.tsx b/src/Spreadsheet.tsx index 70d0b3a9..3d0dc79c 100644 --- a/src/Spreadsheet.tsx +++ b/src/Spreadsheet.tsx @@ -233,17 +233,17 @@ const Spreadsheet = ( }, [onActivate, onBlur, state.active]); // Listen to data changes - const prevDataRef = React.useRef>(state.model.data); + const currentModelDataRef = React.useRef>( + state.model.data + ); React.useEffect(() => { - if (state.model.data !== prevDataRef.current) { - // Call on change only if the data change internal - if (state.model.data !== props.data) { - onChange(state.model.data); - } - } + currentModelDataRef.current = state.model.data; + }, [state.model.data]); - prevDataRef.current = state.model.data; - }, [state.model.data, onChange, props.data]); + React.useEffect(() => { + if (state.lastUpdateDate === null) return; + onChange(currentModelDataRef.current); + }, [state.lastUpdateDate, onChange]); const prevEvaluatedDataRef = React.useRef>( state.model.evaluatedData @@ -252,7 +252,6 @@ const Spreadsheet = ( if (state?.model?.evaluatedData !== prevEvaluatedDataRef?.current) { onEvaluatedDataChange(state?.model?.evaluatedData); } - prevEvaluatedDataRef.current = state.model.evaluatedData; }, [state?.model?.evaluatedData, onEvaluatedDataChange]); diff --git a/src/reducer.test.ts b/src/reducer.test.ts index 1963e08e..501f6ea9 100644 --- a/src/reducer.test.ts +++ b/src/reducer.test.ts @@ -223,7 +223,13 @@ describe("reducer", () => { ], ]; test.each(cases)("%s", (name, state, action, expected) => { - expect(reducer(state, action)).toEqual(expected); + if (name === "setCellData") { + // Addressing this case separately since the test may fail due to slight time-related + // differences between the generation of the expected and obtained results. + const result = reducer(state, action); + result.lastUpdateDate = null; + expect(result).toEqual(expected); + } else expect(reducer(state, action)).toEqual(expected); }); }); diff --git a/src/reducer.ts b/src/reducer.ts index b9cc59c2..437b6521 100644 --- a/src/reducer.ts +++ b/src/reducer.ts @@ -20,6 +20,7 @@ export const INITIAL_STATE: Types.StoreState = { rowDimensions: {}, columnDimensions: {}, lastChanged: null, + lastUpdateDate: null, hasPasted: false, cut: false, dragging: false, @@ -132,6 +133,7 @@ export default function reducer( ...state, model: updateCellValue(state.model, active, cellData), lastChanged: active, + lastUpdateDate: new Date(), }; } case Actions.SET_CELL_DIMENSIONS: { @@ -206,6 +208,7 @@ export default function reducer( hasPasted: true, mode: "view", lastCommit: commit, + lastUpdateDate: new Date(), }; } @@ -276,6 +279,7 @@ export default function reducer( hasPasted: true, mode: "view", lastCommit: acc.commit, + lastUpdateDate: new Date(), }; } @@ -385,6 +389,7 @@ function clear(state: Types.StoreState): Types.StoreState { ...state, model: new Model(createFormulaParser, newData), ...commit(changes), + lastUpdateDate: new Date(), }; } diff --git a/src/types.ts b/src/types.ts index fa47a46a..0b0a1634 100644 --- a/src/types.ts +++ b/src/types.ts @@ -60,6 +60,7 @@ export type StoreState = { >; dragging: boolean; lastChanged: Point | null; + lastUpdateDate: Date | null; lastCommit: null | CellChange[]; }; diff --git a/src/util.test.ts b/src/util.test.ts index 47fb6416..f7ca5ae2 100644 --- a/src/util.test.ts +++ b/src/util.test.ts @@ -54,6 +54,7 @@ const EXAMPLE_STATE: Types.StoreState = { }, }, lastChanged: null, + lastUpdateDate: null, hasPasted: false, cut: false, dragging: false,