feat(EditableCell): improve handling of external updates and user input

This commit is contained in:
ryan 2025-06-27 16:52:46 +03:00
parent afc70a56ba
commit 5f5d8f00d9

View file

@ -26,65 +26,67 @@ export function EditableCell({
className = ''
}: EditableCellProps) {
const [localValue, setLocalValue] = useState(value);
const [isExternalUpdate, setIsExternalUpdate] = useState(false);
const inputRef = useRef<HTMLInputElement>(null);
const textareaRef = useRef<HTMLTextAreaElement>(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<HTMLInputElement | HTMLTextAreaElement>) => {
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') {