diff --git a/src/components/Table/CellValidation.tsx b/src/components/Table/CellValidation.tsx
index 6e566487..c7589786 100644
--- a/src/components/Table/CellValidation.tsx
+++ b/src/components/Table/CellValidation.tsx
@@ -18,6 +18,7 @@ import {
contextMenuTargetAtom,
} from "@src/atoms/tableScope";
import type { TableRow } from "@src/types/table";
+import type { ITableCellProps } from "./withTableCell";
const Dot = styled("div")(({ theme }) => ({
position: "absolute",
@@ -96,6 +97,20 @@ export const CellValidation = memo(function MemoizedCellValidation({
);
}
+ const tableCellComponentProps: ITableCellProps = {
+ ...cell.getContext(),
+ value,
+ focusInsideCell: isSelectedCell && focusInsideCell,
+ setFocusInsideCell: (focusInside: boolean) =>
+ setSelectedCell({
+ path: row.original._rowy_ref.path,
+ columnKey: cell.column.id,
+ focusInside,
+ }),
+ disabled: !canEditCells || cell.column.columnDef.meta?.editable === false,
+ rowHeight,
+ };
+
return (
{renderedValidationTooltip}
- {flexRender(cell.column.columnDef.cell, {
- ...cell.getContext(),
- focusInsideCell: isSelectedCell && focusInsideCell,
- setFocusInsideCell: (focusInside: boolean) =>
- setSelectedCell({
- path: row.original._rowy_ref.path,
- columnKey: cell.column.id,
- focusInside,
- }),
- disabled:
- !canEditCells || cell.column.columnDef.meta?.editable === false,
- rowHeight,
- })}
+ {flexRender(cell.column.columnDef.cell, tableCellComponentProps)}
);
diff --git a/src/components/Table/withTableCell.tsx b/src/components/Table/withTableCell.tsx
index d91eda98..c281423d 100644
--- a/src/components/Table/withTableCell.tsx
+++ b/src/components/Table/withTableCell.tsx
@@ -8,7 +8,7 @@ import {
} from "react";
import useStateRef from "react-usestateref";
import { useSetAtom } from "jotai";
-import { get, isEqual } from "lodash-es";
+import { isEqual } from "lodash-es";
import type { CellContext } from "@tanstack/react-table";
import { Popover, PopoverProps } from "@mui/material";
@@ -32,7 +32,9 @@ export interface ICellOptions {
popoverProps?: Partial;
}
-export interface ITableCellProps extends CellContext {
+export interface ITableCellProps
+ extends CellContext {
+ value: TValue;
focusInsideCell: boolean;
setFocusInsideCell: (focusInside: boolean) => void;
disabled: boolean;
@@ -61,15 +63,12 @@ export default function withTableCell(
function TableCell({
row,
column,
- getValue,
+ value,
focusInsideCell,
setFocusInsideCell,
disabled,
rowHeight,
}: ITableCellProps) {
- // Get the latest value on every re-render of this component
- const value = getValue();
-
// Render inline editor cell after timeout on mount
// to improve scroll performance
const [inlineEditorReady, setInlineEditorReady] = useState(false);
@@ -203,10 +202,7 @@ export default function withTableCell(
return null;
},
(prev, next) => {
- const valueEqual = isEqual(
- get(prev.row.original, prev.column.columnDef.meta!.fieldName),
- get(next.row.original, next.column.columnDef.meta!.fieldName)
- );
+ const valueEqual = isEqual(prev.value, next.value);
const columnEqual = isEqual(
prev.column.columnDef.meta,
next.column.columnDef.meta
@@ -234,12 +230,23 @@ interface IEditorCellManagerProps extends IDisplayCellProps {
function EditorCellManager({
EditorCellComponent,
saveOnUnmount,
+ value,
...props
}: IEditorCellManagerProps) {
- const [localValue, setLocalValue, localValueRef] = useStateRef(props.value);
- const [, setIsDirty, isDirtyRef] = useStateRef(false);
+ // Store local value so we don’t immediately write to db when the user
+ // types in a textbox, for example
+ const [localValue, setLocalValue, localValueRef] = useStateRef(value);
+ // Mark if the user has interacted with this cell and hasn’t saved yet
+ const [isDirty, setIsDirty, isDirtyRef] = useStateRef(false);
const updateField = useSetAtom(updateFieldAtom, tableScope);
+ // When this cell’s data has updated, update the local value if
+ // it’s not dirty and the value is different
+ useEffect(() => {
+ if (!isDirty && !isEqual(value, localValueRef.current))
+ setLocalValue(value);
+ }, [isDirty, localValueRef, setLocalValue, value]);
+
// This is where we update the documents
const handleSubmit = () => {
if (props.disabled || !isDirtyRef.current) return;