From f45d3df3854b4ff3f14c0cd701ffdaf3a63f2e2c Mon Sep 17 00:00:00 2001 From: test Date: Sun, 8 Mar 2026 13:22:43 +0800 Subject: [PATCH] fix(component): fix stale closure in MaterialTypeManagementDialog Fix issue where keyword field was not editable after adding new row via Insert key or Add button. Root cause was incomplete useCallback dependencies in handleKeyDown, causing it to capture stale references to insertNewRow, deleteRow, saveEdit, and cancelEdit functions. Changes: - Wrap insertNewRow with useCallback (deps: isAdmin, currentUsername) - Wrap deleteRow with useCallback (deps: none) - Wrap startEdit with useCallback (deps: rows) - Wrap saveEdit with useCallback (deps: editingCell, editValue) - Wrap cancelEdit with useCallback (deps: none) - Update handleKeyDown dependency array to include all referenced functions This ensures all callbacks have access to the latest props and state, preventing the edit mode initialization failure. Co-Authored-By: Claude Sonnet 4.5 --- .../MaterialTypeManagementDialog.tsx | 66 +++++++++---------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/src/renderer/src/components/MaterialTypeManagementDialog.tsx b/src/renderer/src/components/MaterialTypeManagementDialog.tsx index be7b009..f142a4c 100644 --- a/src/renderer/src/components/MaterialTypeManagementDialog.tsx +++ b/src/renderer/src/components/MaterialTypeManagementDialog.tsx @@ -115,31 +115,8 @@ export const MaterialTypeManagementDialog: React.FC selectedManagers.has(row.record.managerName) || row.state === 'new') }, [rows, isAdmin, selectedManagers]) - // Handle keyboard events - const handleKeyDown = useCallback( - (event: React.KeyboardEvent) => { - if (editingCell) { - if (event.key === 'Enter') { - saveEdit() - } else if (event.key === 'Escape') { - cancelEdit() - } - return - } - - if (event.key === 'Insert') { - event.preventDefault() - insertNewRow() - } else if (event.key === 'Delete' && selectedRowIndex !== null) { - event.preventDefault() - deleteRow(selectedRowIndex) - } - }, - [editingCell, selectedRowIndex] - ) - // Insert new row - const insertNewRow = () => { + const insertNewRow = useCallback(() => { const newRow: RowState = { record: { materialName: '', @@ -157,10 +134,10 @@ export const MaterialTypeManagementDialog: React.FC { + const deleteRow = useCallback((index: number) => { setRows((prev) => { const newRows = [...prev] const row = newRows[index] @@ -174,19 +151,19 @@ export const MaterialTypeManagementDialog: React.FC { + const startEdit = useCallback((rowIndex: number, field: string) => { const row = rows[rowIndex] if (row.state === 'deleted') return setEditingCell({ rowIndex, field }) setEditValue(row.record[field as keyof MaterialTypeRecord] as string) - } + }, [rows]) // Save edit - const saveEdit = () => { + const saveEdit = useCallback(() => { if (!editingCell) return const { rowIndex, field } = editingCell @@ -209,13 +186,36 @@ export const MaterialTypeManagementDialog: React.FC { + const cancelEdit = useCallback(() => { setEditingCell(null) setEditValue('') - } + }, []) + + // Handle keyboard events + const handleKeyDown = useCallback( + (event: React.KeyboardEvent) => { + if (editingCell) { + if (event.key === 'Enter') { + saveEdit() + } else if (event.key === 'Escape') { + cancelEdit() + } + return + } + + if (event.key === 'Insert') { + event.preventDefault() + insertNewRow() + } else if (event.key === 'Delete' && selectedRowIndex !== null) { + event.preventDefault() + deleteRow(selectedRowIndex) + } + }, + [editingCell, selectedRowIndex, insertNewRow, deleteRow, saveEdit, cancelEdit] + ) // Save all changes const handleSave = async () => {