feat(EditableCell): improve handling of external updates and user input
This commit is contained in:
parent
afc70a56ba
commit
5f5d8f00d9
1 changed files with 24 additions and 22 deletions
|
@ -26,65 +26,67 @@ export function EditableCell({
|
||||||
className = ''
|
className = ''
|
||||||
}: EditableCellProps) {
|
}: EditableCellProps) {
|
||||||
const [localValue, setLocalValue] = useState(value);
|
const [localValue, setLocalValue] = useState(value);
|
||||||
const [isExternalUpdate, setIsExternalUpdate] = useState(false);
|
|
||||||
const inputRef = useRef<HTMLInputElement>(null);
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
const textareaRef = useRef<HTMLTextAreaElement>(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(() => {
|
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);
|
setLocalValue(value);
|
||||||
setIsExternalUpdate(true);
|
|
||||||
}
|
}
|
||||||
}, [value, localValue]);
|
lastExternalValueRef.current = value;
|
||||||
|
|
||||||
// Reset external update flag after a short delay
|
// Reset user input flag after a short delay
|
||||||
useEffect(() => {
|
if (isUserInputRef.current) {
|
||||||
if (isExternalUpdate) {
|
|
||||||
const timer = setTimeout(() => {
|
const timer = setTimeout(() => {
|
||||||
setIsExternalUpdate(false);
|
isUserInputRef.current = false;
|
||||||
}, 100);
|
}, 100);
|
||||||
return () => clearTimeout(timer);
|
return () => clearTimeout(timer);
|
||||||
}
|
}
|
||||||
}, [isExternalUpdate]);
|
}, [value, cellKey]);
|
||||||
|
|
||||||
// Handle focus when this cell becomes focused
|
// Handle focus when this cell becomes focused
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (focusedCell === cellKey) {
|
if (focusedCell === cellKey) {
|
||||||
const element = inputType === 'textarea' ? textareaRef.current : inputRef.current;
|
const element = inputType === 'textarea' ? textareaRef.current : inputRef.current;
|
||||||
if (element) {
|
if (element && document.activeElement !== element) {
|
||||||
element.focus();
|
element.focus();
|
||||||
// Select all text when focusing, but not during external updates
|
// Only select text if this is not from user input
|
||||||
if (!isExternalUpdate) {
|
if (!isUserInputRef.current) {
|
||||||
element.select();
|
element.select();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [focusedCell, cellKey, inputType, isExternalUpdate]);
|
}, [focusedCell, cellKey, inputType]);
|
||||||
|
|
||||||
const handleInput = useCallback((e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
|
const handleInput = useCallback((e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
|
||||||
const newValue = e.target.value;
|
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);
|
setLocalValue(newValue);
|
||||||
}, []);
|
}, [cellKey]);
|
||||||
|
|
||||||
const commitInput = useCallback(() => {
|
const commitInput = useCallback(() => {
|
||||||
console.log('Committing input:', localValue);
|
console.log('Committing input for cell:', cellKey, localValue);
|
||||||
onInput(localValue);
|
onInput(localValue);
|
||||||
}, [localValue, onInput]);
|
}, [localValue, onInput, cellKey]);
|
||||||
|
|
||||||
const handleFocus = useCallback(() => {
|
const handleFocus = useCallback(() => {
|
||||||
console.log('Focus gained for key:', cellKey);
|
console.log('Focus gained for cell:', cellKey);
|
||||||
setFocusedCell(cellKey);
|
setFocusedCell(cellKey);
|
||||||
onFocus?.();
|
onFocus?.();
|
||||||
}, [cellKey, setFocusedCell, onFocus]);
|
}, [cellKey, setFocusedCell, onFocus]);
|
||||||
|
|
||||||
const handleBlur = useCallback(() => {
|
const handleBlur = useCallback(() => {
|
||||||
console.log('Focus lost');
|
console.log('Focus lost for cell:', cellKey);
|
||||||
setFocusedCell(null);
|
setFocusedCell(null);
|
||||||
commitInput();
|
commitInput();
|
||||||
onBlur?.();
|
onBlur?.();
|
||||||
}, [setFocusedCell, commitInput, onBlur]);
|
}, [setFocusedCell, commitInput, onBlur, cellKey]);
|
||||||
|
|
||||||
const handleKeyDown = useCallback((e: React.KeyboardEvent) => {
|
const handleKeyDown = useCallback((e: React.KeyboardEvent) => {
|
||||||
if (e.key === 'Enter' && inputType === 'text') {
|
if (e.key === 'Enter' && inputType === 'text') {
|
||||||
|
|
Loading…
Add table
Reference in a new issue