Optimisations to try and lower the number of rerenders required when switching tasks
This commit is contained in:
parent
f530fc7efa
commit
bde4247e29
@ -1,4 +1,4 @@
|
|||||||
import React, { useCallback } from "react";
|
import React, { useCallback, useMemo } from "react";
|
||||||
import {
|
import {
|
||||||
TaskDefinition,
|
TaskDefinition,
|
||||||
TaskMetadata,
|
TaskMetadata,
|
||||||
@ -14,7 +14,7 @@ interface TaskEditorProps {
|
|||||||
onValidate: (taskId: string, isValid: boolean) => void;
|
onValidate: (taskId: string, isValid: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TaskEditor: React.FC<TaskEditorProps> = ({
|
const TaskEditorComponent: React.FC<TaskEditorProps> = ({
|
||||||
task,
|
task,
|
||||||
tasks,
|
tasks,
|
||||||
tasksMetadata,
|
tasksMetadata,
|
||||||
@ -41,23 +41,34 @@ export const TaskEditor: React.FC<TaskEditorProps> = ({
|
|||||||
[onValidate],
|
[onValidate],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const tasksRef = React.useRef(tasks);
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
runValidation(task, tasks, tasksMetadata);
|
tasksRef.current = tasks;
|
||||||
}, [task.config.guid, runValidation]);
|
}, [tasks]);
|
||||||
|
|
||||||
const handleTaskChange = (updatedTask: TaskDefinition) => {
|
React.useEffect(() => {
|
||||||
// Update the task list
|
runValidation(task, tasksRef.current, tasksMetadata);
|
||||||
const updatedTasks = tasks.map((t) =>
|
}, [task.config.guid, runValidation, tasksMetadata]);
|
||||||
t.config.guid === updatedTask.config.guid ? updatedTask : t,
|
|
||||||
);
|
|
||||||
|
|
||||||
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
|
runValidation(updatedTask, updatedTasks, tasksMetadata);
|
||||||
onChange(updatedTask);
|
|
||||||
};
|
|
||||||
|
|
||||||
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 (
|
return (
|
||||||
<div>
|
<div>
|
||||||
@ -83,3 +94,22 @@ export const TaskEditor: React.FC<TaskEditorProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState, useCallback } from "react";
|
||||||
import templateVersionsService, {
|
import templateVersionsService, {
|
||||||
CreateWorkflowTemplateVersion,
|
CreateWorkflowTemplateVersion,
|
||||||
TaskDefinition,
|
TaskDefinition,
|
||||||
@ -60,10 +60,31 @@ const TasksTab: React.FC<TasksTabProps> = ({
|
|||||||
setSelectedTask(tasks[0]);
|
setSelectedTask(tasks[0]);
|
||||||
}, [tasks, taskValidation, selectedTask]);
|
}, [tasks, taskValidation, selectedTask]);
|
||||||
|
|
||||||
const handleTasksChange = (newTasks: TaskDefinition[]) => {
|
const handleTasksChange = React.useCallback(
|
||||||
// Update the parent form state
|
(newTasks: TaskDefinition[]) => {
|
||||||
onTasksChange("tasks", newTasks);
|
// 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 (
|
return (
|
||||||
<div className="two-column-grid no-scroll">
|
<div className="two-column-grid no-scroll">
|
||||||
@ -84,20 +105,7 @@ const TasksTab: React.FC<TasksTabProps> = ({
|
|||||||
tasksMetadata={tasksMetadata}
|
tasksMetadata={tasksMetadata}
|
||||||
task={selectedTask}
|
task={selectedTask}
|
||||||
tasks={tasks}
|
tasks={tasks}
|
||||||
onChange={(updatedTask) => {
|
onChange={handleTaskEditorChange}
|
||||||
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!);
|
|
||||||
}}
|
|
||||||
onValidate={onValidate}
|
onValidate={onValidate}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user