Small optimization for better performance (#4036)
This commit is contained in:
parent
2e174cd4e8
commit
c587a89405
3 changed files with 76 additions and 89 deletions
|
@ -31,7 +31,6 @@ export const MultiValuedStringComponent = ({
|
||||||
addButtonLabel={t("addMultivaluedLabel", {
|
addButtonLabel={t("addMultivaluedLabel", {
|
||||||
fieldLabel: t(label!).toLowerCase(),
|
fieldLabel: t(label!).toLowerCase(),
|
||||||
})}
|
})}
|
||||||
stringify
|
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
);
|
);
|
||||||
|
|
|
@ -6,25 +6,18 @@ import {
|
||||||
TextInputProps,
|
TextInputProps,
|
||||||
} from "@patternfly/react-core";
|
} from "@patternfly/react-core";
|
||||||
import { MinusCircleIcon, PlusCircleIcon } from "@patternfly/react-icons";
|
import { MinusCircleIcon, PlusCircleIcon } from "@patternfly/react-icons";
|
||||||
import { Fragment, useEffect, useState } from "react";
|
import { Fragment, useEffect, useMemo } from "react";
|
||||||
import { useFormContext } from "react-hook-form";
|
import { useFormContext, useWatch } from "react-hook-form";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
function stringToMultiline(value?: string): string[] {
|
function stringToMultiline(value?: string): string[] {
|
||||||
return value ? value.split("##") : [];
|
return typeof value === "string" ? value.split("##") : [];
|
||||||
}
|
}
|
||||||
|
|
||||||
function toStringValue(formValue: string[]): string {
|
function toStringValue(formValue: string[]): string {
|
||||||
return formValue.join("##");
|
return formValue.join("##");
|
||||||
}
|
}
|
||||||
|
|
||||||
type IdValue = {
|
|
||||||
id: number;
|
|
||||||
value: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
const generateId = () => Math.floor(Math.random() * 1000);
|
|
||||||
|
|
||||||
export type MultiLineInputProps = Omit<TextInputProps, "form"> & {
|
export type MultiLineInputProps = Omit<TextInputProps, "form"> & {
|
||||||
name: string;
|
name: string;
|
||||||
addButtonLabel?: string;
|
addButtonLabel?: string;
|
||||||
|
@ -42,50 +35,51 @@ export const MultiLineInput = ({
|
||||||
...rest
|
...rest
|
||||||
}: MultiLineInputProps) => {
|
}: MultiLineInputProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { register, setValue, getValues } = useFormContext();
|
const { register, setValue, control } = useFormContext();
|
||||||
|
const value = useWatch({
|
||||||
|
name,
|
||||||
|
control,
|
||||||
|
defaultValue: defaultValue || "",
|
||||||
|
});
|
||||||
|
|
||||||
const [fields, setFields] = useState<IdValue[]>([]);
|
const fields = useMemo<string[]>(() => {
|
||||||
|
let values = stringify ? stringToMultiline(value as string) : value;
|
||||||
const remove = (index: number) => {
|
|
||||||
update([...fields.slice(0, index), ...fields.slice(index + 1)]);
|
|
||||||
};
|
|
||||||
|
|
||||||
const append = () => {
|
|
||||||
update([...fields, { id: generateId(), value: "" }]);
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateValue = (index: number, value: string) => {
|
|
||||||
update([
|
|
||||||
...fields.slice(0, index),
|
|
||||||
{ ...fields[index], value },
|
|
||||||
...fields.slice(index + 1),
|
|
||||||
]);
|
|
||||||
};
|
|
||||||
|
|
||||||
const update = (values: IdValue[]) => {
|
|
||||||
setFields(values);
|
|
||||||
const fieldValue = values.flatMap((field) => field.value);
|
|
||||||
setValue(name, stringify ? toStringValue(fieldValue) : fieldValue);
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
register(name);
|
|
||||||
let values = stringify
|
|
||||||
? stringToMultiline(getValues(name))
|
|
||||||
: getValues(name);
|
|
||||||
|
|
||||||
values =
|
values =
|
||||||
Array.isArray(values) && values.length !== 0
|
Array.isArray(values) && values.length !== 0
|
||||||
? values
|
? values
|
||||||
: defaultValue || [""];
|
: defaultValue || [""];
|
||||||
|
|
||||||
setFields(values.map((value: string) => ({ value, id: generateId() })));
|
return values;
|
||||||
}, [register, getValues]);
|
}, [value]);
|
||||||
|
|
||||||
|
const remove = (index: number) => {
|
||||||
|
update([...fields.slice(0, index), ...fields.slice(index + 1)]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const append = () => {
|
||||||
|
update([...fields, ""]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateValue = (index: number, value: string) => {
|
||||||
|
update([...fields.slice(0, index), value, ...fields.slice(index + 1)]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const update = (values: string[]) => {
|
||||||
|
const fieldValue = values.flatMap((field) => field);
|
||||||
|
setValue(name, stringify ? toStringValue(fieldValue) : fieldValue, {
|
||||||
|
shouldDirty: true,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
register(name);
|
||||||
|
}, [register]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{fields.map(({ id, value }, index) => (
|
{fields.map((value, index) => (
|
||||||
<Fragment key={id}>
|
<Fragment key={index}>
|
||||||
<InputGroup>
|
<InputGroup>
|
||||||
<TextInput
|
<TextInput
|
||||||
data-testid={name + index}
|
data-testid={name + index}
|
||||||
|
|
|
@ -6,25 +6,18 @@ import {
|
||||||
TextInputProps,
|
TextInputProps,
|
||||||
} from "@patternfly/react-core";
|
} from "@patternfly/react-core";
|
||||||
import { MinusCircleIcon, PlusCircleIcon } from "@patternfly/react-icons";
|
import { MinusCircleIcon, PlusCircleIcon } from "@patternfly/react-icons";
|
||||||
import { Fragment, useEffect, useState } from "react";
|
import { Fragment, useEffect, useMemo } from "react";
|
||||||
import { useFormContext } from "react-hook-form-v7";
|
import { useFormContext, useWatch } from "react-hook-form-v7";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
function stringToMultiline(value?: string): string[] {
|
function stringToMultiline(value?: string): string[] {
|
||||||
return value ? value.split("##") : [];
|
return typeof value === "string" ? value.split("##") : [];
|
||||||
}
|
}
|
||||||
|
|
||||||
function toStringValue(formValue: string[]): string {
|
function toStringValue(formValue: string[]): string {
|
||||||
return formValue.join("##");
|
return formValue.join("##");
|
||||||
}
|
}
|
||||||
|
|
||||||
type IdValue = {
|
|
||||||
id: number;
|
|
||||||
value: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
const generateId = () => Math.floor(Math.random() * 1000);
|
|
||||||
|
|
||||||
export type MultiLineInputProps = Omit<TextInputProps, "form"> & {
|
export type MultiLineInputProps = Omit<TextInputProps, "form"> & {
|
||||||
name: string;
|
name: string;
|
||||||
addButtonLabel?: string;
|
addButtonLabel?: string;
|
||||||
|
@ -42,50 +35,51 @@ export const MultiLineInput = ({
|
||||||
...rest
|
...rest
|
||||||
}: MultiLineInputProps) => {
|
}: MultiLineInputProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { register, setValue, getValues } = useFormContext();
|
const { register, setValue, control } = useFormContext();
|
||||||
|
const value = useWatch({
|
||||||
|
name,
|
||||||
|
control,
|
||||||
|
defaultValue: defaultValue || "",
|
||||||
|
});
|
||||||
|
|
||||||
const [fields, setFields] = useState<IdValue[]>([]);
|
const fields = useMemo<string[]>(() => {
|
||||||
|
let values = stringify ? stringToMultiline(value as string) : value;
|
||||||
const remove = (index: number) => {
|
|
||||||
update([...fields.slice(0, index), ...fields.slice(index + 1)]);
|
|
||||||
};
|
|
||||||
|
|
||||||
const append = () => {
|
|
||||||
update([...fields, { id: generateId(), value: "" }]);
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateValue = (index: number, value: string) => {
|
|
||||||
update([
|
|
||||||
...fields.slice(0, index),
|
|
||||||
{ ...fields[index], value },
|
|
||||||
...fields.slice(index + 1),
|
|
||||||
]);
|
|
||||||
};
|
|
||||||
|
|
||||||
const update = (values: IdValue[]) => {
|
|
||||||
setFields(values);
|
|
||||||
const fieldValue = values.flatMap((field) => field.value);
|
|
||||||
setValue(name, stringify ? toStringValue(fieldValue) : fieldValue);
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
register(name);
|
|
||||||
let values = stringify
|
|
||||||
? stringToMultiline(getValues(name))
|
|
||||||
: getValues(name);
|
|
||||||
|
|
||||||
values =
|
values =
|
||||||
Array.isArray(values) && values.length !== 0
|
Array.isArray(values) && values.length !== 0
|
||||||
? values
|
? values
|
||||||
: defaultValue || [""];
|
: defaultValue || [""];
|
||||||
|
|
||||||
setFields(values.map((value: string) => ({ value, id: generateId() })));
|
return values;
|
||||||
}, [register, getValues]);
|
}, [value]);
|
||||||
|
|
||||||
|
const remove = (index: number) => {
|
||||||
|
update([...fields.slice(0, index), ...fields.slice(index + 1)]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const append = () => {
|
||||||
|
update([...fields, ""]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateValue = (index: number, value: string) => {
|
||||||
|
update([...fields.slice(0, index), value, ...fields.slice(index + 1)]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const update = (values: string[]) => {
|
||||||
|
const fieldValue = values.flatMap((field) => field);
|
||||||
|
setValue(name, stringify ? toStringValue(fieldValue) : fieldValue, {
|
||||||
|
shouldDirty: true,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
register(name);
|
||||||
|
}, [register]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{fields.map(({ id, value }, index) => (
|
{fields.map((value, index) => (
|
||||||
<Fragment key={id}>
|
<Fragment key={index}>
|
||||||
<InputGroup>
|
<InputGroup>
|
||||||
<TextInput
|
<TextInput
|
||||||
data-testid={name + index}
|
data-testid={name + index}
|
||||||
|
|
Loading…
Reference in a new issue