I am using MantineUI as UI library. When I go to the component for managing users, they are shown as table rows and in the last column of each row there is edit icon which when clicked opens modal window with editing options. I have comboboxes for user type and status of account and that works fine. But under that I have two componenets, the first one is combobox that let's you select topic (ComboBoxTopic) and the second component is list of three checkboxes (PermissionsCheckbox). Now what I want to happen is when I change topic under ComboBoxTopic to update view of PermissionsCheckbox so that it shows permissions of that topic, but what happens is that it only shows permissions of topic that was selected before modal is opened. For example when I select another topic, close modal and reopen it, it shows correct permissions. How can I manage to rerender PermissionsCheckbox when selectedTopic changes?
Main component under which modal window can be opened:
import { Text, Badge, Group, Table, ActionIcon, rem, Flex,} from "@mantine/core";
import { modals } from "@mantine/modals";
import { IconPencil } from "@tabler/icons-react";
import { ComboBox } from "./ComboBox";
import { useState } from "react";
import { UpdateUserRequest } from "../../types/types";
import { ComboBoxTopic } from "./ComboBoxTopic";
import userService from "../../services/user.service";
import { notifications } from "@mantine/notifications";
import { PermissionCheckbox } from "./PermissionsCheckbox";
interface Props {
user: any;
topics: any;
reload: any;
}
const statusColors: Record<string, string> = {
REQUESTED: "orange",
APPROVED: "green",
REJECTED: "red",
};
export function User({ user, topics, reload }: Props) {
const updatedUser: UpdateUserRequest = JSON.parse(JSON.stringify(user));
const [selectedTopic, setSelectedTopic] = useState<string>(topics[0].name);
const openModal = () =>
modals.openConfirmModal({
title: `Edit user '${user.username}'`,
children: (
<Flex direction="column" align="center" gap="xl">
<Flex direction="row" align="center" justify="space-evenly" w="100%">
<Flex direction="column" align="center">
Role
<ComboBox
selected={user.role}
type="ROLE"
updatedUser={updatedUser}
/>
</Flex>
<Flex direction="column" align="center">
Status
<ComboBox
selected={user.status}
type="STATUS"
updatedUser={updatedUser}
/>
</Flex>
</Flex>
<Flex direction="column" align="center" gap="lg">
<Flex direction="column" align="center">
Permissions for Topic
<ComboBoxTopic
selected={selectedTopic}
topics={topics}
updatedUser={updatedUser}
setSelected={setSelectedTopic}
/>
</Flex>
<PermissionCheckbox
key={selectedTopic}
selected={selectedTopic}
user={updatedUser}
topics={topics}
/>
</Flex>
</Flex>
),
centered: true,
labels: { confirm: "Save", cancel: "Cancel" },
onConfirm: () => onEditSave(),
});
const onEditSave = () => {
userService
.updateUser(user.id, updatedUser)
.then(() => {
reload();
notifications.show({
title: "Update Succeed",
message: "User was successfully updated",
});
})
.catch(() => {
notifications.show({
title: "Update Failed",
message: "User could not be updated",
});
});
};
return (
<Table.Tr key={user.id}>
<Table.Td>
<Group gap="sm">
<Text fz="sm" fw={500}>
{user.username}
</Text>
</Group>
</Table.Td>
<Table.Td>
<Text fz="sm">{user.role}</Text>
</Table.Td>
<Table.Td>
<Badge color={statusColors[user.status]} variant="light">
{user.status}
</Badge>
</Table.Td>
<Table.Td>
<Text fz="sm">{user.email}</Text>
</Table.Td>
<Table.Td>
<Group gap={0} justify="flex-end">
<ActionIcon variant="subtle" color="gray" onClick={openModal}>
<IconPencil
style={{ width: rem(24), height: rem(24) }}
stroke={1.5}
/>
</ActionIcon>
</Group>
</Table.Td>
</Table.Tr>
);
}
Checkbox component for selecting topic:
import { useState } from "react";
import { CheckIcon, Combobox, Group, Input, InputBase,} from "@mantine/core";
import { UpdateUserRequest } from "../../types/types";
interface Props {
selected: string;
topics?: any;
updatedUser: UpdateUserRequest;
setSelected: any;
}
export function ComboBoxTopic({ selected, topics, setSelected }: Props) {
const combobox = useCombobox({
onDropdownClose: () => combobox.resetSelectedOption(),
onDropdownOpen: (eventSource) => {
if (eventSource === "keyboard") {
combobox.selectActiveOption();
} else {
combobox.updateSelectedOptionIndex("active");
}
},
});
const [value, setValue] = useState<string>(selected);
const options = topics.map((topic: any) => (
<Combobox.Option
value={topic.name}
key={topic.name}
active={topic.name === value}
>
<Group gap="xs">
{topic.name === value && <CheckIcon size={12} />}
<span>{topic.name}</span>
</Group>
</Combobox.Option>
));
return (
<Combobox
store={combobox}
width="40%"
resetSelectionOnOptionHover
withinPortal={false}
onOptionSubmit={(val) => {
setSelected(val);
setValue(val);
combobox.updateSelectedOptionIndex("active");
}}
>
<Combobox.Target targetType="button">
<InputBase
component="button"
type="button"
pointer
rightSection={<Combobox.Chevron />}
rightSectionPointerEvents="none"
onClick={() => combobox.toggleDropdown()}
>
{value || <Input.Placeholder>Pick value</Input.Placeholder>}
</InputBase>
</Combobox.Target>
<Combobox.Dropdown>
<Combobox.Options>{options}</Combobox.Options>
</Combobox.Dropdown>
</Combobox>
);
}
And the component for showing permissions:
import { Checkbox, Flex } from "@mantine/core";
import { UpdateUserRequest } from "../../types/types";
import { useEffect, useState } from "react";
interface Props {
selected: string;
topics: any;
user: UpdateUserRequest;
}
export function PermissionCheckbox({ selected, topics, user }: Props) {
const [topicPermissions, setTopicPermissions] = useState<any>();
useEffect(() => {
const topic = topics.find((t: any) => t.name === selected);
setTopicPermissions(
user.permissions.find((p: any) => p.idTopic === topic.id)
);
}, [selected]);
return (
<>
{topicPermissions && (
<Flex direction="column" gap="md" justify="center" align="flex-start">
<Checkbox
label="Write"
checked={topicPermissions.write}
onChange={(event) => {
if (topicPermissions)
setTopicPermissions((prevTopicPermissions: any) => ({
...prevTopicPermissions,
delete: event.currentTarget.checked,
}));
}}
/>
<Checkbox
label="Update"
checked={topicPermissions.update}
onChange={(event) => {
if (topicPermissions)
setTopicPermissions((prevTopicPermissions: any) => ({
...prevTopicPermissions,
update: event.currentTarget.checked,
}));
}}
/>
<Checkbox
label="Delete"
checked={topicPermissions.delete}
onChange={(event) => {
if (topicPermissions)
setTopicPermissions((prevTopicPermissions: any) => ({
...prevTopicPermissions,
delete: event.currentTarget.checked,
}));
}}
/>
</Flex>
)}
</>
);
}
I've tried to force update on checkboxes when selected changes but it simply doesn't work. For some reason even the useEffect under PermissionsCheckbox isn't called when selected changes. What could I do to fix this?