React JS中更新状态多切换的处理



描述

[![在此输入图像描述][1]][1]

我有一个有很多行的表,每一行的表数据都有一个开关形式。即使我点击了第二行的开关,我发送的代码也只创建了一个对象,这意味着数据被覆盖了。我的期望是,当我单击新行时,将添加一个新的状态对象。以下是初始状态、处理程序和突变:

状态:

const [checkedValues, setCheckedValues] = useState({
add: true,
modify: true,
delete: true,
view: true,
export: true,
permission: "",
});

经办人:

const onCheckboxChange = (event, permission) => {
setCheckedValues({
...checkedValues,
[event.target.name]: event.target.checked,
permission: permission,
});
};

突变:

const assignPermissionPromise = assignPermission({
variables: {
input: {
groupId: groupId,
permissionCodes: [
{
add: checkedValues.add,
modify: checkedValues.modify,
export: checkedValues.export,
delete: checkedValues.delete,
view: checkedValues.view,
permission: checkedValues.permission,
}
],
},
},
});

还有一个组件需要更改获取复选框更新值的方式:

<>
<td>
<Form.Check
id={`lihat-${index}-${subMenuItemIndex}`}
type="switch"
name="view"
defaultChecked={checked.view}
value={checked.view}
onChange={onChange}
/>
</td>
<td>
<Form.Check
id={`tambah-${index}-${subMenuItemIndex}`}
type="switch"
name="add"
defaultChecked={checked.add}
value={checked.add}
onChange={onChange}
/>
</td>
<td>
<Form.Check
id={`ubah-${index}-${subMenuItemIndex}`}
type="switch"
name="modify"
defaultChecked={checked.modify}
value={checked.modify}
onChange={onChange}
/>
</td>
<td>
<Form.Check
id={`hapus-${index}-${subMenuItemIndex}`}
type="switch"
name="delete"
defaultChecked={checked.delete}
value={checked.delete}
onChange={onChange}
/>
</td>
<td>
<Form.Check
id={`export-${index}-${subMenuItemIndex}`}
type="switch"
name="export"
defaultChecked={checked.export}
value={checked.export}
onChange={onChange}
/>
</td>
</>

预期输出

预期的结果是,当我单击第二行或应用多个角色权限时,放置在数组中的对象数量应该会增加。示例:

[
{
add: true,
modify: true,
delete: true,
view: true,
export: true,
permission: "user",
},
{
add: true,
modify: true,
delete: true,
view: true,
export: true,
permission: "user_group",
},
]

任何帮助都将不胜感激,谢谢。

完整源代码。

formKontroldanHakAksesTambah.js(父级)

const FormKontrolDanHakAksesTambah = () => {
const history = useHistory();
useEffect(() => {
document.title = "Tambah Group Role";
}, []);
// state for input form group and switches
const [value, setValue] = useState({
groupId: "",
groupName: "",
groupDesc: "",
});
const [checkedValues, setCheckedValues] = useState(
{
add: true,
modify: true,
delete: true,
view: true,
export: true,
permission: "",
},
);
useEffect(() => {
console.log(checkedValues);
}, [checkedValues]);
const onChange = (event) => {
setValue({
...value,
[event.target.name]: event.target.value,
});
};
const onCheckboxChange = (event, permission) => {
setCheckedValues({
...checkedValues,
[event.target.name]: event.target.checked,
permission: permission
});
};

const [createUserGroup, { loading: loadingCreateUserGroup }] = useMutation(
CREATE_USER_GROUP,
{
onCompleted: () => {
history.push("/konfigurasi/grup-dan-hak-akses-pengguna");
},
onError: (err) => {
console.error(err.message);
},
}
);
const [assignPermission, { loading: assignPermsLoading }] = useMutation(
ASSIGN_PERMS,
{
onError: (err) => {
console.error(JSON.stringify(err, null, 2));
console.log(assignPermission);
},
}
);
if (loadingCreateUserGroup || assignPermsLoading)
return (
<>
<Loading />
</>
);
const handleSubmitGroupBaru = async (e) => {
e.preventDefault();
if (
value.groupId === "" ||
value.groupName === "" ||
value.groupDesc === ""
) {
// Menampilkan pesan error jika ada field yang kosong
Swal.fire({
icon: "error",
title: "Silakan lengkapi semua field",
});
return;
}
try {
// Membuat promise untuk mutasi createUserGroup
const createGroupPromise = createUserGroup({
variables: {
input: {
groupId: value.groupId,
groupName: value.groupName,
groupDesc: value.groupDesc,
},
},
awaitRefetchQueries: true,
refetchQueries: [{ query: GET_ALL_USER_GROUP }, "getAllUserGroup"],
});
// Menunggu hasil promise mutasi createUserGroup
const {
data: {
createUserGroup: { groupId },
},
} = await createGroupPromise;
// Membuat promise untuk mutasi assignPermission
const assignPermissionPromise = assignPermission({
variables: {
input: {
groupId: groupId,
permissionCodes: [
{
add: checkedValues.add,
modify: checkedValues.modify,
export: checkedValues.export,
delete: checkedValues.delete,
view: checkedValues.view,
permission: checkedValues.permission,
}
],
},
},
});
// Menunggu hasil promise mutasi assignPermission
await assignPermissionPromise;
Swal.fire({
icon: "success",
title: "Akun Grup berhasil ditambahkan",
showConfirmButton: false,
timer: 1500,
});
} catch (err) {
Swal.fire({
icon: "error",
title: err.message,
});
}
};
return (
<>
<section className={`${styles.FormAksi}`}>
<Container className={`${styles.container}`}>
<Row>
<Col>
<Card className={`${styles.customCard}`}>
<Card.Title className={`${styles.customCardHeader}`}>
<p className="text-uppercase base-lg text-semi-bold">
Informasi Grup Akun
</p>
</Card.Title>
<Card.Body>
<FormCreateGroup onChange={onChange} value={value} />
</Card.Body>
</Card>
</Col>
</Row>
<Row>
<Col>
<Card className="border-0 mt-5">
<Card.Title>
<p className="text-uppercase base-lg text-semi-bold mt-2 mx-2">
Kontrol Akses
</p>
</Card.Title>
<Card.Body>
<TableRole
checkedValues={checkedValues}
onChange={onCheckboxChange}
/>
</Card.Body>
</Card>
</Col>
</Row>
</Container>
<Divider className="my-3" />
<div className="d-flex justify-content-end">
<ButtonSecondary
variant="solid"
wider="true"
onClick={handleSubmitGroupBaru}
className="mt-5"
>
{" "}
<FaSave className="mx-2" /> SIMPAN PERUBAHAN
</ButtonSecondary>
</div>
</section>
</>
);
};

TableRole.js(子)

export default function TableRole({ checkedValues, onChange }) {
const tableHeader = [
"No",
"Menu",
"Sub Menu",
"Lihat",
"Tambah",
"Ubah",
"Hapus",
"Export",
];
const tableData = [
{
id: 1,
menu: "Dashboard",
submenu: ["-"],
},
{
id: 2,
menu: "Konfigurasi/Pengaturan",
submenu: [
{
name: 'Akun Pengguna',
permission: 'user',
permissionIndex: 1,
},
{
name: 'Grup',
permission: 'user_group',
permissionIndex: 2
}
]
},
];
return (
<Table className="table-responsive">
<thead
style={{ backgroundColor: "#ECEFF1" }}
className="txt-blue-grey-700 base-md text-bold"
>
<tr>
{tableHeader.map((header, index) => (
<th
key={index}
className="txt-blue-grey-700 base-md text-bold text-center"
style={{ padding: "0.75rem" }}
>
{header}
</th>
))}
</tr>
</thead>
<tbody className="text-center">
{tableData.map((row, rowIndex) => (
<React.Fragment key={rowIndex}>
<RoleRow
index={rowIndex + 1}
menu={row.menu}
submenu={row.submenu}
checked={checkedValues}
onChange={onChange}
/>
</React.Fragment>
))}
</tbody>
</Table>
);
}
const RoleRow = ({ index, menu, submenu ,checked,onChange }) => {
return (
<>
<tr>
<td rowSpan={submenu.length + 1}>{index}</td>
<td rowSpan={submenu.length + 1}>{menu}</td>
</tr>
{submenu.map((subMenuItem, subMenuItemIndex) => (
<tr key={`${index}-${subMenuItemIndex}-${subMenuItem.permission}`}>
<td>{subMenuItem.name}</td>  
<PermissionCheckbox
checked={checked[subMenuItemIndex]}
onChange={(e) => onChange(e, subMenuItem.permission, index)}
/>
</tr>
))}
</>
);
};
const PermissionCheckbox = ({ index, subMenuItemIndex, checked, onChange, perms }) => (
<>
<td>
<Form.Check
id={`lihat-${index}-${subMenuItemIndex}`}
type="switch"
name="view"
defaultChecked={checked.view}
value={checked.view}
onChange={onChange}
/>
</td>
<td>
<Form.Check
id={`tambah-${index}-${subMenuItemIndex}`}
type="switch"
name="add"
defaultChecked={checked.add}
value={checked.add}
onChange={onChange}
/>
</td>
<td>
<Form.Check
id={`ubah-${index}-${subMenuItemIndex}`}
type="switch"
name="modify"
defaultChecked={checked.modify}
value={checked.modify}
onChange={onChange}
/>
</td>
<td>
<Form.Check
id={`hapus-${index}-${subMenuItemIndex}`}
type="switch"
name="delete"
defaultChecked={checked.delete}
value={checked.delete}
onChange={onChange}
/>
</td>
<td>
<Form.Check
id={`export-${index}-${subMenuItemIndex}`}
type="switch"
name="export"
defaultChecked={checked.export}
value={checked.export}
onChange={onChange}
/>
</td>
</>
);

这是代码沙盒演示:

https://codesandbox.io/s/test-checkbox-40tm39?file=/src/App.js:392-410[1] :https://i.stack.imgur.com/qMHUm.png

看起来checkedValues是一个对象。所以每次点击开关时,它都会被覆盖。我建议为checkedValues创建一个数组,然后更新checkedValues的单个对象。类似于此,

const [checkedValues, setCheckedValues] = useState([]);
const onCheckboxChange = (event, permission) => {
setCheckedValues((prevState) => [
...prevState,
{
[event.target.name]: event.target.checked,
permission: permission,
},
]);
};

assignPermission突变中,

const assignPermissionPromise = assignPermission({
variables: {
input: {
groupId: groupId,
permissionCodes: checkedValues.map((checkedValue) => ({
add: checkedValue.add,
modify: checkedValue.modify,
export: checkedValue.export,
delete: checkedValue.delete,
view: checkedValue.view,
permission: checkedValue.permission,
})),
},
},
});

Form.Check组件中,将权限字符串作为道具传递:

<Form.Check
id={`lihat-${index}-${subMenuItemIndex}`}
type="switch"
name="view"
defaultChecked={checked.view}
value={checked.view}
onChange={(event) =>
onCheckboxChange(event, "permission string")
}
/>