21642: Change conditionaltabs to render tabs as hidden to avoid re-renders
[arvados.git] / services / workbench2 / src / components / conditional-tabs / conditional-tabs.tsx
index 74f2ecf4f91e0d100e41342d5a4dba0d48ae4ee4..499e84df8a335b1b4c419aacd924ec30d425dbad 100644 (file)
@@ -2,14 +2,19 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
-import React, { ReactNode, useEffect, useState } from "react";
+import React, { CSSProperties, ReactElement, useEffect, useState } from "react";
 import { Tabs, Tab } from "@material-ui/core";
 import { TabsProps } from "@material-ui/core/Tabs";
 
-type TabData = {
+interface ComponentWithHidden {
+    styles: CSSProperties;
+    hidden: boolean;
+};
+
+export type TabData = {
     show: boolean;
     label: string;
-    content: ReactNode;
+    content: ReactElement<ComponentWithHidden>;
 };
 
 type ConditionalTabsProps = {
@@ -19,7 +24,6 @@ type ConditionalTabsProps = {
 export const ConditionalTabs = (props: Omit<TabsProps, 'value' | 'onChange'> & ConditionalTabsProps) => {
     const [tabState, setTabState] = useState(0);
     const visibleTabs = props.tabs.filter(tab => tab.show);
-    const activeTab = visibleTabs[tabState];
     const visibleTabNames = visibleTabs.map(tab => tab.label).join();
 
     const handleTabChange = (event: React.MouseEvent<HTMLElement>, value: number) => {
@@ -37,8 +41,11 @@ export const ConditionalTabs = (props: Omit<TabsProps, 'value' | 'onChange'> & C
             {...props}
             value={tabState}
             onChange={handleTabChange} >
-            {visibleTabs.map(tab => <Tab label={tab.label} />)}
+            {visibleTabs.map(tab => <Tab key={tab.label} label={tab.label} />)}
         </Tabs>
-        {activeTab && activeTab.content}
+
+        {visibleTabs.map((tab, i) => (
+            React.cloneElement(tab.content, {hidden: i !== tabState})
+        ))}
     </>;
 };