🐛 fix(EditNodeModal): add missing useRef import to fix compilation error

✨ feat(EditNodeModal): use useRef to store and update data instead of useState to improve performance and prevent unnecessary re-renders

🐛 fix(EditNodeModal): fix references to myData.node to myData.current.node to correctly access the current node data
This commit is contained in:
Cristhian Zanforlin Lousa 2023-09-26 19:07:34 -03:00
commit a0c4da7d76

View file

@ -1,5 +1,5 @@
import { cloneDeep } from "lodash"; import { cloneDeep } from "lodash";
import { ReactNode, forwardRef, useContext, useEffect, useState } from "react"; import { ReactNode, forwardRef, useContext, useEffect, useRef, useState } from "react";
import CodeAreaComponent from "../../components/codeAreaComponent"; import CodeAreaComponent from "../../components/codeAreaComponent";
import DictComponent from "../../components/dictComponent"; import DictComponent from "../../components/dictComponent";
import Dropdown from "../../components/dropdownComponent"; import Dropdown from "../../components/dropdownComponent";
@ -56,7 +56,10 @@ const EditNodeModal = forwardRef(
ref ref
) => { ) => {
const [modalOpen, setModalOpen] = useState(open ?? false); const [modalOpen, setModalOpen] = useState(open ?? false);
const [myData, setMyData] = useState(data);
const myData = useRef(data);
const { setTabsState, tabId } = useContext(TabsContext); const { setTabsState, tabId } = useContext(TabsContext);
const { reactFlowInstance } = useContext(typesContext); const { reactFlowInstance } = useContext(typesContext);
let disabled = let disabled =
@ -65,19 +68,15 @@ const EditNodeModal = forwardRef(
.some((edge) => edge.targetHandle === data.id) ?? false; .some((edge) => edge.targetHandle === data.id) ?? false;
function changeAdvanced(n) { function changeAdvanced(n) {
let newData = cloneDeep(data); myData.current.node!.template[n].advanced = !myData.current.node!.template[n].advanced;
newData.node!.template[n].advanced = !newData.node!.template[n].advanced;
setMyData(newData);
} }
const handleOnNewValue = (newValue: any, name) => { const handleOnNewValue = (newValue: any, name) => {
let newData = cloneDeep(data); myData.current.node!.template[name].value = newValue;
newData.node!.template[name].value = newValue;
setMyData(newData);
}; };
useEffect(() => { useEffect(() => {
setMyData(data); // reset data to what it is on node when opening modal myData.current = data // reset data to what it is on node when opening modal
onClose!(modalOpen); onClose!(modalOpen);
}, [modalOpen]); }, [modalOpen]);
@ -89,14 +88,13 @@ const EditNodeModal = forwardRef(
open={modalOpen} open={modalOpen}
setOpen={setModalOpen} setOpen={setModalOpen}
onChangeOpenModal={(open) => { onChangeOpenModal={(open) => {
let newData = cloneDeep(data); myData.current = data;
setMyData(newData);
}} }}
> >
<BaseModal.Trigger>{children}</BaseModal.Trigger> <BaseModal.Trigger>{children}</BaseModal.Trigger>
<BaseModal.Header description={myData.node?.description!}> <BaseModal.Header description={myData.current.node?.description!}>
<span className="pr-2">{myData.type}</span> <span className="pr-2">{myData.current.type}</span>
<Badge variant="secondary">ID: {myData.id}</Badge> <Badge variant="secondary">ID: {myData.current.id}</Badge>
</BaseModal.Header> </BaseModal.Header>
<BaseModal.Content> <BaseModal.Content>
<div className="flex pb-2"> <div className="flex pb-2">
@ -129,67 +127,67 @@ const EditNodeModal = forwardRef(
</TableRow> </TableRow>
</TableHeader> </TableHeader>
<TableBody className="p-0"> <TableBody className="p-0">
{Object.keys(myData.node!.template) {Object.keys(myData.current.node!.template)
.filter( .filter(
(templateParam) => (templateParam) =>
templateParam.charAt(0) !== "_" && templateParam.charAt(0) !== "_" &&
myData.node?.template[templateParam].show && myData.current.node?.template[templateParam].show &&
(myData.node.template[templateParam].type === (myData.current.node.template[templateParam].type ===
"str" || "str" ||
myData.node.template[templateParam].type === myData.current.node.template[templateParam].type ===
"bool" || "bool" ||
myData.node.template[templateParam].type === myData.current.node.template[templateParam].type ===
"float" || "float" ||
myData.node.template[templateParam].type === myData.current.node.template[templateParam].type ===
"code" || "code" ||
myData.node.template[templateParam].type === myData.current.node.template[templateParam].type ===
"prompt" || "prompt" ||
myData.node.template[templateParam].type === myData.current.node.template[templateParam].type ===
"file" || "file" ||
myData.node.template[templateParam].type === myData.current.node.template[templateParam].type ===
"int" || "int" ||
myData.node.template[templateParam].type === myData.current.node.template[templateParam].type ===
"dict" || "dict" ||
myData.node.template[templateParam].type === myData.current.node.template[templateParam].type ===
"NestedDict") "NestedDict")
) )
.map((templateParam, index) => ( .map((templateParam, index) => (
<TableRow key={index} className="h-10"> <TableRow key={index} className="h-10">
<TableCell className="truncate p-0 text-center text-sm text-foreground sm:px-3"> <TableCell className="truncate p-0 text-center text-sm text-foreground sm:px-3">
{myData.node?.template[templateParam].name {myData.current.node?.template[templateParam].name
? myData.node.template[templateParam].name ? myData.current.node.template[templateParam].name
: myData.node?.template[templateParam] : myData.current.node?.template[templateParam]
.display_name} .display_name}
</TableCell> </TableCell>
<TableCell className="w-[300px] p-0 text-center text-xs text-foreground "> <TableCell className="w-[300px] p-0 text-center text-xs text-foreground ">
{myData.node?.template[templateParam].type === {myData.current.node?.template[templateParam].type ===
"str" && "str" &&
!myData.node.template[templateParam].options ? ( !myData.current.node.template[templateParam].options ? (
<div className="mx-auto"> <div className="mx-auto">
{myData.node.template[templateParam].list ? ( {myData.current.node.template[templateParam].list ? (
<InputListComponent <InputListComponent
editNode={true} editNode={true}
disabled={disabled} disabled={disabled}
value={ value={
!myData.node.template[templateParam] !myData.current.node.template[templateParam]
.value || .value ||
myData.node.template[templateParam] myData.current.node.template[templateParam]
.value === "" .value === ""
? [""] ? [""]
: myData.node.template[templateParam] : myData.current.node.template[templateParam]
.value .value
} }
onChange={(value: string[]) => { onChange={(value: string[]) => {
handleOnNewValue(value, templateParam); handleOnNewValue(value, templateParam);
}} }}
/> />
) : myData.node.template[templateParam] ) : myData.current.node.template[templateParam]
.multiline ? ( .multiline ? (
<TextAreaComponent <TextAreaComponent
disabled={disabled} disabled={disabled}
editNode={true} editNode={true}
value={ value={
myData.node.template[templateParam] myData.current.node.template[templateParam]
.value ?? "" .value ?? ""
} }
onChange={(value: string | string[]) => { onChange={(value: string | string[]) => {
@ -201,11 +199,11 @@ const EditNodeModal = forwardRef(
editNode={true} editNode={true}
disabled={disabled} disabled={disabled}
password={ password={
myData.node.template[templateParam] myData.current.node.template[templateParam]
.password ?? false .password ?? false
} }
value={ value={
myData.node.template[templateParam] myData.current.node.template[templateParam]
.value ?? "" .value ?? ""
} }
onChange={(value) => { onChange={(value) => {
@ -214,40 +212,40 @@ const EditNodeModal = forwardRef(
/> />
)} )}
</div> </div>
) : myData.node?.template[templateParam].type === ) : myData.current.node?.template[templateParam].type ===
"NestedDict" ? ( "NestedDict" ? (
<div className="mt-2 w-full"> <div className="mt-2 w-full">
<DictComponent <DictComponent
disabled={disabled} disabled={disabled}
editNode={true} editNode={true}
value={ value={
myData.node!.template[templateParam] myData.current.node!.template[templateParam]
.value ?? { .value ?? {
yourkey: "value", yourkey: "value",
} }
} }
onChange={(newValue) => { onChange={(newValue) => {
myData.node!.template[ myData.current.node!.template[
templateParam templateParam
].value = newValue; ].value = newValue;
handleOnNewValue(newValue, templateParam); handleOnNewValue(newValue, templateParam);
}} }}
/> />
</div> </div>
) : myData.node?.template[templateParam].type === ) : myData.current.node?.template[templateParam].type ===
"dict" ? ( "dict" ? (
<div className="mt-2 w-full"> <div className="mt-2 w-full">
<KeypairListComponent <KeypairListComponent
disabled={disabled} disabled={disabled}
editNode={true} editNode={true}
value={ value={
myData.node!.template[templateParam].value myData.current.node!.template[templateParam].value
?.length === 0 || ?.length === 0 ||
!myData.node!.template[templateParam] !myData.current.node!.template[templateParam]
.value .value
? [{ "": "" }] ? [{ "": "" }]
: convertObjToArray( : convertObjToArray(
myData.node!.template[templateParam] myData.current.node!.template[templateParam]
.value .value
) )
} }
@ -255,7 +253,7 @@ const EditNodeModal = forwardRef(
onChange={(newValue) => { onChange={(newValue) => {
const valueToNumbers = const valueToNumbers =
convertValuesToNumbers(newValue); convertValuesToNumbers(newValue);
myData.node!.template[ myData.current.node!.template[
templateParam templateParam
].value = valueToNumbers; ].value = valueToNumbers;
setErrorDuplicateKey( setErrorDuplicateKey(
@ -268,14 +266,14 @@ const EditNodeModal = forwardRef(
}} }}
/> />
</div> </div>
) : myData.node?.template[templateParam].type === ) : myData.current.node?.template[templateParam].type ===
"bool" ? ( "bool" ? (
<div className="ml-auto"> <div className="ml-auto">
{" "} {" "}
<ToggleShadComponent <ToggleShadComponent
disabled={disabled} disabled={disabled}
enabled={ enabled={
myData.node.template[templateParam].value myData.current.node.template[templateParam].value
} }
setEnabled={(isEnabled) => { setEnabled={(isEnabled) => {
handleOnNewValue( handleOnNewValue(
@ -286,14 +284,14 @@ const EditNodeModal = forwardRef(
size="small" size="small"
/> />
</div> </div>
) : myData.node?.template[templateParam].type === ) : myData.current.node?.template[templateParam].type ===
"float" ? ( "float" ? (
<div className="mx-auto"> <div className="mx-auto">
<FloatComponent <FloatComponent
disabled={disabled} disabled={disabled}
editNode={true} editNode={true}
value={ value={
myData.node.template[templateParam] myData.current.node.template[templateParam]
.value ?? "" .value ?? ""
} }
onChange={(value) => { onChange={(value) => {
@ -301,34 +299,34 @@ const EditNodeModal = forwardRef(
}} }}
/> />
</div> </div>
) : myData.node?.template[templateParam].type === ) : myData.current.node?.template[templateParam].type ===
"str" && "str" &&
myData.node.template[templateParam].options ? ( myData.current.node.template[templateParam].options ? (
<div className="mx-auto"> <div className="mx-auto">
<Dropdown <Dropdown
numberOfOptions={nodeLength} numberOfOptions={nodeLength}
editNode={true} editNode={true}
options={ options={
myData.node.template[templateParam] myData.current.node.template[templateParam]
.options .options
} }
onSelect={(value) => onSelect={(value) =>
handleOnNewValue(value, templateParam) handleOnNewValue(value, templateParam)
} }
value={ value={
myData.node.template[templateParam] myData.current.node.template[templateParam]
.value ?? "Choose an option" .value ?? "Choose an option"
} }
></Dropdown> ></Dropdown>
</div> </div>
) : myData.node?.template[templateParam].type === ) : myData.current.node?.template[templateParam].type ===
"int" ? ( "int" ? (
<div className="mx-auto"> <div className="mx-auto">
<IntComponent <IntComponent
disabled={disabled} disabled={disabled}
editNode={true} editNode={true}
value={ value={
myData.node.template[templateParam] myData.current.node.template[templateParam]
.value ?? "" .value ?? ""
} }
onChange={(value) => { onChange={(value) => {
@ -336,25 +334,25 @@ const EditNodeModal = forwardRef(
}} }}
/> />
</div> </div>
) : myData.node?.template[templateParam].type === ) : myData.current.node?.template[templateParam].type ===
"file" ? ( "file" ? (
<div className="mx-auto"> <div className="mx-auto">
<InputFileComponent <InputFileComponent
editNode={true} editNode={true}
disabled={disabled} disabled={disabled}
value={ value={
myData.node.template[templateParam] myData.current.node.template[templateParam]
.value ?? "" .value ?? ""
} }
onChange={(value: string | string[]) => { onChange={(value: string | string[]) => {
handleOnNewValue(value, templateParam); handleOnNewValue(value, templateParam);
}} }}
fileTypes={ fileTypes={
myData.node.template[templateParam] myData.current.node.template[templateParam]
.fileTypes .fileTypes
} }
suffixes={ suffixes={
myData.node.template[templateParam] myData.current.node.template[templateParam]
.suffixes .suffixes
} }
onFileChange={(filePath: string) => { onFileChange={(filePath: string) => {
@ -364,19 +362,19 @@ const EditNodeModal = forwardRef(
}} }}
></InputFileComponent> ></InputFileComponent>
</div> </div>
) : myData.node?.template[templateParam].type === ) : myData.current.node?.template[templateParam].type ===
"prompt" ? ( "prompt" ? (
<div className="mx-auto"> <div className="mx-auto">
<PromptAreaComponent <PromptAreaComponent
field_name={templateParam} field_name={templateParam}
editNode={true} editNode={true}
disabled={disabled} disabled={disabled}
nodeClass={myData.node} nodeClass={myData.current.node}
setNodeClass={(nodeClass) => { setNodeClass={(nodeClass) => {
myData.node = nodeClass; myData.current.node = nodeClass;
}} }}
value={ value={
myData.node.template[templateParam] myData.current.node.template[templateParam]
.value ?? "" .value ?? ""
} }
onChange={(value: string | string[]) => { onChange={(value: string | string[]) => {
@ -384,7 +382,7 @@ const EditNodeModal = forwardRef(
}} }}
/> />
</div> </div>
) : myData.node?.template[templateParam].type === ) : myData.current.node?.template[templateParam].type ===
"code" ? ( "code" ? (
<div className="mx-auto"> <div className="mx-auto">
<CodeAreaComponent <CodeAreaComponent
@ -399,7 +397,7 @@ const EditNodeModal = forwardRef(
disabled={disabled} disabled={disabled}
editNode={true} editNode={true}
value={ value={
myData.node.template[templateParam] myData.current.node.template[templateParam]
.value ?? "" .value ?? ""
} }
onChange={(value: string | string[]) => { onChange={(value: string | string[]) => {
@ -407,7 +405,7 @@ const EditNodeModal = forwardRef(
}} }}
/> />
</div> </div>
) : myData.node?.template[templateParam].type === ) : myData.current.node?.template[templateParam].type ===
"Any" ? ( "Any" ? (
"-" "-"
) : ( ) : (
@ -418,12 +416,13 @@ const EditNodeModal = forwardRef(
<div className="items-center text-center"> <div className="items-center text-center">
<ToggleShadComponent <ToggleShadComponent
enabled={ enabled={
!myData.node?.template[templateParam] !myData.current.node?.template[templateParam]
.advanced .advanced
} }
setEnabled={(e) => setEnabled={(e) =>{
changeAdvanced(templateParam) changeAdvanced(templateParam)
} }
}
disabled={disabled} disabled={disabled}
size="small" size="small"
/> />
@ -443,7 +442,8 @@ const EditNodeModal = forwardRef(
<Button <Button
className="mt-3" className="mt-3"
onClick={() => { onClick={() => {
setData(cloneDeep(myData)); //saves data with actual state of modal const newData = cloneDeep(myData.current);
myData.current = newData;
//@ts-ignore //@ts-ignore
setTabsState((prev: TabsState) => { setTabsState((prev: TabsState) => {
return { return {