React Dynamic Table 和嵌套地图
React Dynamic Table and Nested Maps
我必须做一个 users/permissions table,其中“权限”是 X 轴,“用户”是 Y 轴。 table 的其余部分填充了指示 X 用户是否具有 Y 权限的复选框。
这两个都是动态长度,每个 API 都可以某种方式访问另一个。即:Permissions API 对每个 Permission 都有一组具有该权限的用户。
反之亦然,用户 API 对每个用户都有一组用户拥有的权限。
我在使用嵌套地图时遇到问题,我觉得这样做成本很高? (如果有40个权限,350个用户,我们说的是14k个checkbox)
如何保存每个复选框的状态?没关系,我正在尝试使用检查 useState 做什么?我还需要一种方法来将更新的权限发送给另一个 API.
在 return 语句中使用“isChecked”常量,我强制复选框只为 true 或 false,并且在单击时无法更改。
在 return 声明中,我应该映射“支票”,但由于某种原因没有像我期望的那样被填充。
[{
用户ID:号码,
permID:数字,
检查:布尔值
},
{
用户ID:号码,
permID:数字,
检查:布尔值
},
ETC
]
代码看起来像这样:
const [checks, setChecks] = useState([]);
const users = //GET to users API
const permissions = //GET to permissions API
const mapPermissions = () => {
users.map((user: any) => {
permissions.map((permission: any) => {
setChecks((prevState: any) => [
...prevState,
{
userID: user.id,
permID: permission.id,
//group_lists is an array of Permissions ID that current user has.
checked: user.group_lists ? user.group_lists.includes(permission.id) : false,
},
]);
});
});
};
useEffect(() => {
mapPermissions();
}, []);
return (
<TableContainer component={Paper}>
<Table className={styles.table}>
<TableHead>
<TableRow>
<TableCell className={styles.blank} />
{permissions.map((permission) => (
<TableCell key={permission.id} className={styles.header}>
{permission.name}
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
// Should be replacing this for "checks" state map.
{users.map((user: any) => (
<TableRow key={user.id}>
<TableCell
className={styles.left}
>{`${user.first_name} ${user.last_name} (${user.username})`}</TableCell>
{permissions.map((permission: any) => {
const isChecked = user.group_lists
? user.group_lists.includes(permission.id)
: false;
return (
<TableCell key={`${user.id}-${permission.id}`}>
<input
type="checkbox"
checked={isChecked}
onChange={(e: ChangeEvent<HTMLInputElement>) => {
console.log({
user: user.id,
permid: permission.id,
currentState: isChecked,
futureState: e.target.checked,
});
}}
/>
</TableCell>
);
})}
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
);
如果需要,我愿意删除所有内容。提前致谢:)
我稍微简化了您的代码片段,让我更容易上手。我会选择这样的东西
type UpdatesType = {
userId: number;
permissionId: number;
operation: 'add' | 'remove';
}
export const UserPermissionTable: React.FC = ({}) => {
const [updates, setUpdates] = useState<UpdatesType[]>([]);
const users = // get from api
const permissions = // get from api
return (
<div>
<table>
<thead>
<tr>
<td />
{permissions.map((permission) => (
<td key={permission.id}>{permission.name}</td>
))}
</tr>
</thead>
<tbody>
{users.map((user: any) => (
<tr key={user.id}>
<td>{`${user.name}`}</td>
{permissions.map((permission: any) => {
const isChecked = user.group_lists
? user.group_lists.includes(permission.id)
: false;
return (
<td key={`${user.id}-${permission.id}`}>
<input
type="checkbox"
defaultChecked={isChecked}
onChange={(e) => {
setUpdates((prev) => [
...prev,
{
userId: user.id,
permissionId: permission.id,
operation: e.target.checked ? "add" : "remove",
},
]);
}}
/>
</td>
);
})}
</tr>
))}
</tbody>
</table>
</div>
);
};
要点:
- 您不需要自己处理每个复选框的状态,您可以使用
defaultChecked
属性并在复选框更改时更新 updates
对象
- 在我的示例中,我将所有更新放入一个数组中,然后您可以将此数组与操作一起发送到任何您想要的地方 - 您也可以在发送到 API 之前删除重复的操作,但这不是目的这个问题
我必须做一个 users/permissions table,其中“权限”是 X 轴,“用户”是 Y 轴。 table 的其余部分填充了指示 X 用户是否具有 Y 权限的复选框。 这两个都是动态长度,每个 API 都可以某种方式访问另一个。即:Permissions API 对每个 Permission 都有一组具有该权限的用户。 反之亦然,用户 API 对每个用户都有一组用户拥有的权限。
我在使用嵌套地图时遇到问题,我觉得这样做成本很高? (如果有40个权限,350个用户,我们说的是14k个checkbox)
如何保存每个复选框的状态?没关系,我正在尝试使用检查 useState 做什么?我还需要一种方法来将更新的权限发送给另一个 API.
在 return 语句中使用“isChecked”常量,我强制复选框只为 true 或 false,并且在单击时无法更改。
在 return 声明中,我应该映射“支票”,但由于某种原因没有像我期望的那样被填充。
[{ 用户ID:号码, permID:数字, 检查:布尔值 }, { 用户ID:号码, permID:数字, 检查:布尔值 }, ETC ]
代码看起来像这样:
const [checks, setChecks] = useState([]);
const users = //GET to users API
const permissions = //GET to permissions API
const mapPermissions = () => {
users.map((user: any) => {
permissions.map((permission: any) => {
setChecks((prevState: any) => [
...prevState,
{
userID: user.id,
permID: permission.id,
//group_lists is an array of Permissions ID that current user has.
checked: user.group_lists ? user.group_lists.includes(permission.id) : false,
},
]);
});
});
};
useEffect(() => {
mapPermissions();
}, []);
return (
<TableContainer component={Paper}>
<Table className={styles.table}>
<TableHead>
<TableRow>
<TableCell className={styles.blank} />
{permissions.map((permission) => (
<TableCell key={permission.id} className={styles.header}>
{permission.name}
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
// Should be replacing this for "checks" state map.
{users.map((user: any) => (
<TableRow key={user.id}>
<TableCell
className={styles.left}
>{`${user.first_name} ${user.last_name} (${user.username})`}</TableCell>
{permissions.map((permission: any) => {
const isChecked = user.group_lists
? user.group_lists.includes(permission.id)
: false;
return (
<TableCell key={`${user.id}-${permission.id}`}>
<input
type="checkbox"
checked={isChecked}
onChange={(e: ChangeEvent<HTMLInputElement>) => {
console.log({
user: user.id,
permid: permission.id,
currentState: isChecked,
futureState: e.target.checked,
});
}}
/>
</TableCell>
);
})}
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
);
如果需要,我愿意删除所有内容。提前致谢:)
我稍微简化了您的代码片段,让我更容易上手。我会选择这样的东西
type UpdatesType = {
userId: number;
permissionId: number;
operation: 'add' | 'remove';
}
export const UserPermissionTable: React.FC = ({}) => {
const [updates, setUpdates] = useState<UpdatesType[]>([]);
const users = // get from api
const permissions = // get from api
return (
<div>
<table>
<thead>
<tr>
<td />
{permissions.map((permission) => (
<td key={permission.id}>{permission.name}</td>
))}
</tr>
</thead>
<tbody>
{users.map((user: any) => (
<tr key={user.id}>
<td>{`${user.name}`}</td>
{permissions.map((permission: any) => {
const isChecked = user.group_lists
? user.group_lists.includes(permission.id)
: false;
return (
<td key={`${user.id}-${permission.id}`}>
<input
type="checkbox"
defaultChecked={isChecked}
onChange={(e) => {
setUpdates((prev) => [
...prev,
{
userId: user.id,
permissionId: permission.id,
operation: e.target.checked ? "add" : "remove",
},
]);
}}
/>
</td>
);
})}
</tr>
))}
</tbody>
</table>
</div>
);
};
要点:
- 您不需要自己处理每个复选框的状态,您可以使用
defaultChecked
属性并在复选框更改时更新updates
对象 - 在我的示例中,我将所有更新放入一个数组中,然后您可以将此数组与操作一起发送到任何您想要的地方 - 您也可以在发送到 API 之前删除重复的操作,但这不是目的这个问题