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 <noreply@anthropic.com>
This commit is contained in:
@@ -115,31 +115,8 @@ export const MaterialTypeManagementDialog: React.FC<MaterialTypeManagementDialog
|
||||
return rows.filter((row) => 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<MaterialTypeManagementDialog
|
||||
}, 0)
|
||||
return [...prev, newRow]
|
||||
})
|
||||
}
|
||||
}, [isAdmin, currentUsername])
|
||||
|
||||
// Delete row
|
||||
const deleteRow = (index: number) => {
|
||||
const deleteRow = useCallback((index: number) => {
|
||||
setRows((prev) => {
|
||||
const newRows = [...prev]
|
||||
const row = newRows[index]
|
||||
@@ -174,19 +151,19 @@ export const MaterialTypeManagementDialog: React.FC<MaterialTypeManagementDialog
|
||||
return newRows
|
||||
})
|
||||
setSelectedRowIndex(null)
|
||||
}
|
||||
}, [])
|
||||
|
||||
// Start editing a cell
|
||||
const startEdit = (rowIndex: number, field: string) => {
|
||||
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<MaterialTypeManagementDialog
|
||||
|
||||
setEditingCell(null)
|
||||
setEditValue('')
|
||||
}
|
||||
}, [editingCell, editValue])
|
||||
|
||||
// Cancel edit
|
||||
const cancelEdit = () => {
|
||||
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 () => {
|
||||
|
||||
Reference in New Issue
Block a user