diff --git a/src/modules/manager/workflowTemplates/components/TasksEditor.tsx b/src/modules/manager/workflowTemplates/components/TasksEditor.tsx index 0b0be1b..2badfba 100644 --- a/src/modules/manager/workflowTemplates/components/TasksEditor.tsx +++ b/src/modules/manager/workflowTemplates/components/TasksEditor.tsx @@ -1,4 +1,4 @@ -import React, { useCallback } from "react"; +import React, { useCallback, useMemo } from "react"; import { TaskDefinition, TaskMetadata, @@ -14,7 +14,7 @@ interface TaskEditorProps { onValidate: (taskId: string, isValid: boolean) => void; } -export const TaskEditor: React.FC = ({ +const TaskEditorComponent: React.FC = ({ task, tasks, tasksMetadata, @@ -41,23 +41,34 @@ export const TaskEditor: React.FC = ({ [onValidate], ); + const tasksRef = React.useRef(tasks); React.useEffect(() => { - runValidation(task, tasks, tasksMetadata); - }, [task.config.guid, runValidation]); + tasksRef.current = tasks; + }, [tasks]); - const handleTaskChange = (updatedTask: TaskDefinition) => { - // Update the task list - const updatedTasks = tasks.map((t) => - t.config.guid === updatedTask.config.guid ? updatedTask : t, - ); + React.useEffect(() => { + runValidation(task, tasksRef.current, tasksMetadata); + }, [task.config.guid, runValidation, tasksMetadata]); - runValidation(updatedTask, updatedTasks, tasksMetadata); + const handleTaskChange = useCallback( + (updatedTask: TaskDefinition) => { + // Update the task list + const updatedTasks = tasks.map((t) => + t.config.guid === updatedTask.config.guid ? updatedTask : t, + ); - // Bubble updated task up - onChange(updatedTask); - }; + runValidation(updatedTask, updatedTasks, tasksMetadata); - const taskMeta = tasksMetadata.find((t) => t.taskType === task.type); + // Bubble updated task up + onChange(updatedTask); + }, + [tasks, tasksMetadata, runValidation, onChange], + ); + + const taskMeta = useMemo( + () => tasksMetadata.find((t) => t.taskType === task.type), + [tasksMetadata, task.type], + ); return (
@@ -83,3 +94,22 @@ export const TaskEditor: React.FC = ({
); }; + +export const TaskEditor = React.memo( + TaskEditorComponent, + (prevProps, nextProps) => { + const taskIdChanged = + prevProps.task.config.guid !== nextProps.task.config.guid; + const metaChanged = prevProps.tasksMetadata !== nextProps.tasksMetadata; + const onChangeChanged = prevProps.onChange !== nextProps.onChange; + const onValidateChanged = prevProps.onValidate !== nextProps.onValidate; + + // Skip tasks comparison - we use a ref to access it + return !( + taskIdChanged || + metaChanged || + onChangeChanged || + onValidateChanged + ); + }, +); diff --git a/src/modules/manager/workflowTemplates/components/TasksTab.tsx b/src/modules/manager/workflowTemplates/components/TasksTab.tsx index 804a00a..0e81959 100644 --- a/src/modules/manager/workflowTemplates/components/TasksTab.tsx +++ b/src/modules/manager/workflowTemplates/components/TasksTab.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from "react"; +import React, { useEffect, useState, useCallback } from "react"; import templateVersionsService, { CreateWorkflowTemplateVersion, TaskDefinition, @@ -60,10 +60,31 @@ const TasksTab: React.FC = ({ setSelectedTask(tasks[0]); }, [tasks, taskValidation, selectedTask]); - const handleTasksChange = (newTasks: TaskDefinition[]) => { - // Update the parent form state - onTasksChange("tasks", newTasks); - }; + const handleTasksChange = React.useCallback( + (newTasks: TaskDefinition[]) => { + // Update the parent form state + onTasksChange("tasks", newTasks); + }, + [onTasksChange], + ); + + const handleTaskEditorChange = React.useCallback( + (updatedTask: TaskDefinition) => { + const newTasks = tasks.map((t) => + t.config.guid === updatedTask.config.guid ? updatedTask : t, + ); + + handleTasksChange(newTasks); + + // Use the updated object from the array, not the raw updatedTask + const updatedFromArray = newTasks.find( + (t) => t.config.guid === updatedTask.config.guid, + ); + + setSelectedTask(updatedFromArray!); + }, + [tasks, handleTasksChange], + ); return (
@@ -84,20 +105,7 @@ const TasksTab: React.FC = ({ tasksMetadata={tasksMetadata} task={selectedTask} tasks={tasks} - onChange={(updatedTask) => { - const newTasks = tasks.map((t) => - t.config.guid === updatedTask.config.guid ? updatedTask : t, - ); - - handleTasksChange(newTasks); - - // Use the updated object from the array, not the raw updatedTask - const updatedFromArray = newTasks.find( - (t) => t.config.guid === updatedTask.config.guid, - ); - - setSelectedTask(updatedFromArray!); - }} + onChange={handleTaskEditorChange} onValidate={onValidate} />