Fix infinite renders on event-type edit page (#2820)

This commit is contained in:
Hariom Balhara 2022-05-23 23:29:09 +05:30 committed by GitHub
parent 67770bf878
commit f0a36f8194
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 33 additions and 54 deletions

View File

@ -8,6 +8,8 @@ Fixes # (issue)
Loom Video: https://www.loom.com/
-->
**Environment**: Staging(main branch) / Production
## Type of change
<!-- Please delete options that are not relevant. -->

View File

@ -1,57 +1,31 @@
import { CheckIcon, XIcon } from "@heroicons/react/outline";
import React, { useEffect, useState } from "react";
import { MultiValue } from "react-select";
import React from "react";
import { Props } from "react-select";
import { useLocale } from "@lib/hooks/useLocale";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import Avatar from "@components/ui/Avatar";
import Select from "@components/ui/form/Select";
type CheckedSelectValue = {
type CheckedSelectOption = {
avatar: string;
label: string;
value: string;
disabled?: boolean;
}[];
export type CheckedSelectProps = {
defaultValue?: CheckedSelectValue;
placeholder?: string;
name?: string;
options: CheckedSelectValue;
onChange: (options: CheckedSelectValue) => void;
disabled: boolean;
};
export const CheckedSelect = (props: CheckedSelectProps) => {
const { onChange } = props;
const [selectedOptions, setSelectedOptions] = useState<CheckedSelectValue>(props.defaultValue || []);
export const CheckedSelect = ({
options = [],
value = [],
...props
}: Omit<Props<CheckedSelectOption, true>, "value" | "onChange"> & {
value?: readonly CheckedSelectOption[];
onChange: (value: readonly CheckedSelectOption[]) => void;
}) => {
const { t } = useLocale();
useEffect(() => {
onChange(selectedOptions);
}, [onChange, selectedOptions]);
const options = props.options.map((option) => ({
...option,
disabled: !!selectedOptions.find((selectedOption) => selectedOption.value === option.value),
}));
const removeOption = (value: string) =>
setSelectedOptions(selectedOptions.filter((option) => option.value !== value));
const changeHandler = (selections: MultiValue<CheckedSelectValue[number]>) =>
selections.forEach((selected) => {
if (selectedOptions.find((option) => option.value === selected.value)) {
removeOption(selected.value);
return;
}
setSelectedOptions(selectedOptions.concat(selected));
});
return (
<>
<Select<CheckedSelectValue[number], true>
<Select
styles={{
option: (styles, { isDisabled }) => ({
...styles,
@ -73,11 +47,11 @@ export const CheckedSelect = (props: CheckedSelectProps) => {
</div>
)}
options={options}
value={value}
isMulti
// value={props.placeholder || t("select")}
onChange={changeHandler}
{...props}
/>
{selectedOptions.map((option) => (
{value.map((option) => (
<div key={option.value} className="border-1 border p-2 font-medium">
<Avatar
className="inline h-6 w-6 rounded-full ltr:mr-2 rtl:ml-2"
@ -86,7 +60,7 @@ export const CheckedSelect = (props: CheckedSelectProps) => {
/>
{option.label}
<XIcon
onClick={() => changeHandler([option])}
onClick={() => props.onChange(value.filter((item) => item.value !== option.value))}
className="float-right mt-0.5 h-5 w-5 cursor-pointer text-neutral-500"
/>
</div>
@ -95,6 +69,4 @@ export const CheckedSelect = (props: CheckedSelectProps) => {
);
};
CheckedSelect.displayName = "CheckedSelect";
export default CheckedSelect;

View File

@ -148,6 +148,7 @@ const SuccessRedirectEdit = <T extends UseFormReturn<FormValues>>({
const { t } = useLocale();
const proUpgradeRequired = !isSuccessRedirectAvailable(eventType);
const [modalOpen, setModalOpen] = useState(false);
return (
<>
<hr className="border-neutral-200" />
@ -233,6 +234,7 @@ const AvailabilitySelect = ({
const EventTypePage = (props: inferSSRProps<typeof getServerSideProps>) => {
const { t } = useLocale();
const PERIOD_TYPES = [
{
type: "ROLLING" as const,
@ -1189,16 +1191,19 @@ const EventTypePage = (props: inferSSRProps<typeof getServerSideProps>) => {
name="users"
control={formMethods.control}
defaultValue={eventType.users.map((user) => user.id.toString())}
render={() => (
render={({ field: { onChange, value } }) => (
<CheckedSelect
disabled={false}
onChange={(options) => {
formMethods.setValue(
"users",
options.map((user) => user.value)
);
}}
defaultValue={eventType.users.map(mapUserToValue)}
isDisabled={false}
onChange={(options) => onChange(options.map((user) => user.value))}
value={value
.map(
(userId) =>
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
teamMembers
.map(mapUserToValue)
.find((member) => member.value === userId)!
)
.filter(Boolean)}
options={teamMembers.map(mapUserToValue)}
placeholder={t("add_attendees")}
/>