自定义组件CheckboxLabels
是否应在每次handleCheckboxChange
调用后检索不同的checked
属性?当前我无法在关闭封装的上层列表之前将单击的复选框设置为选中状态。只有打开和关闭上层列表才会更新嵌套复选框组件的状态。
type CheckboxLabelsProps = {
columns: string[]
table: string
checked: Map<string, boolean>
handleCheckboxChange: (event: React.ChangeEvent<HTMLInputElement>) => void
}
function CheckboxLabels({ columns, table, checked, handleCheckboxChange }: CheckboxLabelsProps) {
return (
<FormGroup>
{columns.map((column, index) => (
<FormControlLabel
key={column}
label={column}
value={`${table}-${column}`}
control={<Checkbox checked={checked.has(`${table}-${column}`) ? checked.get(`${table}-${column}`) : false} onChange={handleCheckboxChange} />}
/>
))}
</FormGroup>
);
}
export default function NestedList({ items }: PropsType) {
const [open, setOpen] = React.useState([] as boolean[]);
const [checked, setChecked] = React.useState(new Map() as Map<string, boolean>);
useEffect(() => {
// sets open state as array of false
}, [items])
useEffect(() => {
// sets checked state for each nested checkbox element as false
}, [])
const handleCheckboxChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const [table, column] = event.target.value.split('-');
const newChecked = checked;
const key = `${table}-${column}`;
newChecked.set(key, !checked.get(`${table}-${column}`));
setChecked(newChecked);
};
const handleClick = (index: number) => {
const collapsedIndex: number = index;
const newOpen = [...open];
newOpen[collapsedIndex] = !(open[collapsedIndex]);
setOpen(newOpen);
};
return (
<List>
{items.map((item, index) =>
{
const tables = Object.keys(item.payload.columns);
const columnsForTable = new Map<string, string[]>();
tables.forEach((table) => {
const key = table;
const value = item.payload.columns[table];
columnsForTable.set(key, value);
});
const columnsFT = Object.entries(Object.fromEntries(columnsForTable.entries()));
return columnsFT.map(([table, columns]: [string, string[]], index ) =>
(
<Box key={table}>
<ListItemButton onClick={() => handleClick(index)}>
<ListItemIcon>
<InboxIcon />
</ListItemIcon>
<ListItemText primary={table} />
{open[index] ? <ExpandLess /> : <ExpandMore />}
</ListItemButton>
<Collapse in={open[index]} timeout="auto" unmountOnExit>
<List key={table} component="div" disablePadding>
<ListItem sx={{ pl: 4 }}>
<Box sx={{ display: 'flex', flexDirection: 'column', ml: 3 }}>
<CheckboxLabels columns={columns} table={table} checked={checked} handleCheckboxChange={handleCheckboxChange}/>
</Box>
</ListItem>
</List>
</Collapse>
</Box>
))
})
}
</List>
);
}
1条答案
按热度按时间vs91vp4v1#
问题在于您的
handleCheckboxChange
实现;您应该创建checked
Map的新副本,而不是重用旧副本。这是因为,作为性能优化,React仅在新状态值与旧状态值不同时调用setState
后重新呈现(我相信通过使用Object.is()
作为相等的概念)但是,通过重用相同的Map示例,checked
Map的引用值不会改变。这样“React”就永远不知道要放弃了。以下
handleCheckboxChange
实现应该可以解决您的问题: