From c587a89405352576c0b970e9aae1bc34e06a0ad4 Mon Sep 17 00:00:00 2001 From: Erik Jan de Wit Date: Tue, 17 Jan 2023 16:26:35 +0100 Subject: [PATCH] Small optimization for better performance (#4036) --- .../dynamic/MultivaluedStringComponent.tsx | 1 - .../multi-line-input/MultiLineInput.tsx | 82 +++++++++---------- .../hook-form-v7/MultiLineInput.tsx | 82 +++++++++---------- 3 files changed, 76 insertions(+), 89 deletions(-) diff --git a/apps/admin-ui/src/components/dynamic/MultivaluedStringComponent.tsx b/apps/admin-ui/src/components/dynamic/MultivaluedStringComponent.tsx index 2977a29a8e..a0eb9ee26b 100644 --- a/apps/admin-ui/src/components/dynamic/MultivaluedStringComponent.tsx +++ b/apps/admin-ui/src/components/dynamic/MultivaluedStringComponent.tsx @@ -31,7 +31,6 @@ export const MultiValuedStringComponent = ({ addButtonLabel={t("addMultivaluedLabel", { fieldLabel: t(label!).toLowerCase(), })} - stringify /> ); diff --git a/apps/admin-ui/src/components/multi-line-input/MultiLineInput.tsx b/apps/admin-ui/src/components/multi-line-input/MultiLineInput.tsx index c2acdbf1e7..90e4429c0a 100644 --- a/apps/admin-ui/src/components/multi-line-input/MultiLineInput.tsx +++ b/apps/admin-ui/src/components/multi-line-input/MultiLineInput.tsx @@ -6,25 +6,18 @@ import { TextInputProps, } from "@patternfly/react-core"; import { MinusCircleIcon, PlusCircleIcon } from "@patternfly/react-icons"; -import { Fragment, useEffect, useState } from "react"; -import { useFormContext } from "react-hook-form"; +import { Fragment, useEffect, useMemo } from "react"; +import { useFormContext, useWatch } from "react-hook-form"; import { useTranslation } from "react-i18next"; function stringToMultiline(value?: string): string[] { - return value ? value.split("##") : []; + return typeof value === "string" ? value.split("##") : []; } function toStringValue(formValue: string[]): string { return formValue.join("##"); } -type IdValue = { - id: number; - value: string; -}; - -const generateId = () => Math.floor(Math.random() * 1000); - export type MultiLineInputProps = Omit & { name: string; addButtonLabel?: string; @@ -42,50 +35,51 @@ export const MultiLineInput = ({ ...rest }: MultiLineInputProps) => { const { t } = useTranslation(); - const { register, setValue, getValues } = useFormContext(); + const { register, setValue, control } = useFormContext(); + const value = useWatch({ + name, + control, + defaultValue: defaultValue || "", + }); - const [fields, setFields] = useState([]); - - 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); + const fields = useMemo(() => { + let values = stringify ? stringToMultiline(value as string) : value; values = Array.isArray(values) && values.length !== 0 ? values : defaultValue || [""]; - setFields(values.map((value: string) => ({ value, id: generateId() }))); - }, [register, getValues]); + return values; + }, [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 ( <> - {fields.map(({ id, value }, index) => ( - + {fields.map((value, index) => ( + Math.floor(Math.random() * 1000); - export type MultiLineInputProps = Omit & { name: string; addButtonLabel?: string; @@ -42,50 +35,51 @@ export const MultiLineInput = ({ ...rest }: MultiLineInputProps) => { const { t } = useTranslation(); - const { register, setValue, getValues } = useFormContext(); + const { register, setValue, control } = useFormContext(); + const value = useWatch({ + name, + control, + defaultValue: defaultValue || "", + }); - const [fields, setFields] = useState([]); - - 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); + const fields = useMemo(() => { + let values = stringify ? stringToMultiline(value as string) : value; values = Array.isArray(values) && values.length !== 0 ? values : defaultValue || [""]; - setFields(values.map((value: string) => ({ value, id: generateId() }))); - }, [register, getValues]); + return values; + }, [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 ( <> - {fields.map(({ id, value }, index) => ( - + {fields.map((value, index) => ( +