You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airflow.apache.org by bb...@apache.org on 2022/03/10 18:23:44 UTC

[airflow] 01/01: Reduce rerendering of TaskName component

This is an automated email from the ASF dual-hosted git repository.

bbovenzi pushed a commit to branch memoize-task-name
in repository https://gitbox.apache.org/repos/asf/airflow.git

commit c55280f04eace2e02523b31cd2760a6bc5e7e4eb
Author: Brent Bovenzi <br...@gmail.com>
AuthorDate: Thu Mar 10 13:22:31 2022 -0500

    Reduce rerendering of TaskName component
---
 airflow/www/static/js/tree/TaskName.jsx       | 64 +++++++++++++++++++++++++++
 airflow/www/static/js/tree/renderTaskRows.jsx | 46 ++++---------------
 2 files changed, 73 insertions(+), 37 deletions(-)

diff --git a/airflow/www/static/js/tree/TaskName.jsx b/airflow/www/static/js/tree/TaskName.jsx
new file mode 100644
index 0000000..a80f4d5
--- /dev/null
+++ b/airflow/www/static/js/tree/TaskName.jsx
@@ -0,0 +1,64 @@
+/*!
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React from 'react';
+import {
+  Box,
+  Text,
+  Flex,
+} from '@chakra-ui/react';
+import { FiChevronUp, FiChevronDown } from 'react-icons/fi';
+
+const TaskName = ({
+  isGroup = false, isMapped = false, onToggle, isOpen, level, taskName,
+}) => (
+  <Box _groupHover={{ backgroundColor: 'rgba(113, 128, 150, 0.1)' }} transition="background-color 0.2s">
+    <Flex
+      as={isGroup ? 'button' : 'div'}
+      onClick={onToggle}
+      color={level > 4 && 'white'}
+      aria-label={taskName}
+      title={taskName}
+      mr={4}
+      width="100%"
+      backgroundColor={`rgba(203, 213, 224, ${0.25 * level})`}
+      alignItems="center"
+    >
+      <Text
+        display="inline"
+        fontSize="12px"
+        ml={level * 4 + 4}
+        isTruncated
+      >
+        {taskName}
+        {isMapped && (
+          ' [ ]'
+        )}
+      </Text>
+      {isGroup && (
+        isOpen ? <FiChevronDown data-testid="open-group" /> : <FiChevronUp data-testid="closed-group" />
+      )}
+    </Flex>
+  </Box>
+);
+
+// Only rerender the component if props change
+const MemoizedTaskName = React.memo(TaskName);
+
+export default MemoizedTaskName;
diff --git a/airflow/www/static/js/tree/renderTaskRows.jsx b/airflow/www/static/js/tree/renderTaskRows.jsx
index 170c6c4..89e0a53 100644
--- a/airflow/www/static/js/tree/renderTaskRows.jsx
+++ b/airflow/www/static/js/tree/renderTaskRows.jsx
@@ -19,19 +19,18 @@
 
 /* global localStorage */
 
-import React from 'react';
+import React, { useCallback } from 'react';
 import {
   Tr,
   Td,
   Box,
-  Text,
   Flex,
   useDisclosure,
   Collapse,
 } from '@chakra-ui/react';
-import { FiChevronUp, FiChevronDown } from 'react-icons/fi';
 
 import StatusBox from './StatusBox';
+import TaskName from './TaskName';
 
 import { getMetaValue } from '../utils';
 
@@ -52,39 +51,6 @@ const renderTaskRows = ({
   />
 ));
 
-const TaskName = ({
-  isGroup = false, isMapped = false, onToggle, isOpen, level, taskName,
-}) => (
-  <Box _groupHover={{ backgroundColor: 'rgba(113, 128, 150, 0.1)' }} transition="background-color 0.2s">
-    <Flex
-      as={isGroup ? 'button' : 'div'}
-      onClick={() => isGroup && onToggle()}
-      color={level > 4 && 'white'}
-      aria-label={taskName}
-      title={taskName}
-      mr={4}
-      width="100%"
-      backgroundColor={`rgba(203, 213, 224, ${0.25 * level})`}
-      alignItems="center"
-    >
-      <Text
-        display="inline"
-        fontSize="12px"
-        ml={level * 4 + 4}
-        isTruncated
-      >
-        {taskName}
-        {isMapped && (
-          ' [ ]'
-        )}
-      </Text>
-      {isGroup && (
-        isOpen ? <FiChevronDown data-testid="open-group" /> : <FiChevronUp data-testid="closed-group" />
-      )}
-    </Flex>
-  </Box>
-);
-
 const TaskInstances = ({ task, containerRef, dagRunIds }) => (
   <Flex justifyContent="flex-end">
     {dagRunIds.map((runId) => {
@@ -124,6 +90,12 @@ const Row = (props) => {
   };
   const { isOpen, onToggle } = useDisclosure({ defaultIsOpen: isGroupId, onClose, onOpen });
 
+  // assure the function is the same across renders
+  const memoizedToggle = useCallback(
+    () => isGroup && onToggle(),
+    [onToggle, isGroup],
+  );
+
   const parentTasks = task.id.split('.');
   parentTasks.splice(-1);
 
@@ -150,7 +122,7 @@ const Row = (props) => {
         >
           <Collapse in={isFullyOpen}>
             <TaskName
-              onToggle={onToggle}
+              onToggle={memoizedToggle}
               isGroup={isGroup}
               isMapped={task.isMapped}
               taskName={taskName}