From 5f5d8f00d9a111db0fe37dfaee235c21747d4422 Mon Sep 17 00:00:00 2001 From: ryan Date: Fri, 27 Jun 2025 16:52:46 +0300 Subject: [PATCH] feat(EditableCell): improve handling of external updates and user input --- src/components/EditableCell.tsx | 46 +++++++++++++++++---------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/src/components/EditableCell.tsx b/src/components/EditableCell.tsx index a76d3db..14cb15a 100644 --- a/src/components/EditableCell.tsx +++ b/src/components/EditableCell.tsx @@ -26,65 +26,67 @@ export function EditableCell({ className = '' }: EditableCellProps) { const [localValue, setLocalValue] = useState(value); - const [isExternalUpdate, setIsExternalUpdate] = useState(false); const inputRef = useRef(null); const textareaRef = useRef(null); + const lastExternalValueRef = useRef(value); + const isUserInputRef = useRef(false); - // Update local value when prop changes (including external updates) + // Update local value when prop changes (only for genuine external updates) useEffect(() => { - if (value !== localValue) { + // Only update if this is a genuine external change (not from user input) + if (value !== lastExternalValueRef.current && !isUserInputRef.current) { + console.log('External value change detected for cell:', cellKey, value); setLocalValue(value); - setIsExternalUpdate(true); } - }, [value, localValue]); - - // Reset external update flag after a short delay - useEffect(() => { - if (isExternalUpdate) { + lastExternalValueRef.current = value; + + // Reset user input flag after a short delay + if (isUserInputRef.current) { const timer = setTimeout(() => { - setIsExternalUpdate(false); + isUserInputRef.current = false; }, 100); return () => clearTimeout(timer); } - }, [isExternalUpdate]); + }, [value, cellKey]); // Handle focus when this cell becomes focused useEffect(() => { if (focusedCell === cellKey) { const element = inputType === 'textarea' ? textareaRef.current : inputRef.current; - if (element) { + if (element && document.activeElement !== element) { element.focus(); - // Select all text when focusing, but not during external updates - if (!isExternalUpdate) { + // Only select text if this is not from user input + if (!isUserInputRef.current) { element.select(); } } } - }, [focusedCell, cellKey, inputType, isExternalUpdate]); + }, [focusedCell, cellKey, inputType]); const handleInput = useCallback((e: React.ChangeEvent) => { const newValue = e.target.value; - console.log('Input event:', newValue); + console.log('Input event for cell:', cellKey, newValue); + isUserInputRef.current = true; // Mark as user input setLocalValue(newValue); - }, []); + }, [cellKey]); const commitInput = useCallback(() => { - console.log('Committing input:', localValue); + console.log('Committing input for cell:', cellKey, localValue); onInput(localValue); - }, [localValue, onInput]); + }, [localValue, onInput, cellKey]); const handleFocus = useCallback(() => { - console.log('Focus gained for key:', cellKey); + console.log('Focus gained for cell:', cellKey); setFocusedCell(cellKey); onFocus?.(); }, [cellKey, setFocusedCell, onFocus]); const handleBlur = useCallback(() => { - console.log('Focus lost'); + console.log('Focus lost for cell:', cellKey); setFocusedCell(null); commitInput(); onBlur?.(); - }, [setFocusedCell, commitInput, onBlur]); + }, [setFocusedCell, commitInput, onBlur, cellKey]); const handleKeyDown = useCallback((e: React.KeyboardEvent) => { if (e.key === 'Enter' && inputType === 'text') {