Small optimization for better performance (#4036)

This commit is contained in:
Erik Jan de Wit 2023-01-17 16:26:35 +01:00 committed by GitHub
parent 2e174cd4e8
commit c587a89405
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 76 additions and 89 deletions

View file

@ -31,7 +31,6 @@ export const MultiValuedStringComponent = ({
addButtonLabel={t("addMultivaluedLabel", { addButtonLabel={t("addMultivaluedLabel", {
fieldLabel: t(label!).toLowerCase(), fieldLabel: t(label!).toLowerCase(),
})} })}
stringify
/> />
</FormGroup> </FormGroup>
); );

View file

@ -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}

View file

@ -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}