Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React tabs - switching destroys component, need to maintain the same component

Tags:

tabs

reactjs

I am trying to make a multi-tabbed SPA with React and Material-UI. I use code from this demo as an example: https://codesandbox.io/s/qlq1j47l2w

It appears that if I follow the aforementioned example, I end up returning new instance of the component with tab contents each time I navigate between the tabs:

      <Tabs
        value={value}
        onChange={this.handleChange}
        indicatorColor="primary"
        textColor="primary"
        scrollable
        scrollButtons="auto"
      >
        <Tab label="Tab 1" />
        <Tab label="Tab 2" />
      </Tabs>
    </AppBar>
    {value === 0 && <Tab1Contents/>}
    {value === 1 && <Tab2Contents/>}

As Tab1Contents is a form, I would like its internal state to be retained, instead of loading a new instance of the component, which the code above appears to do.

What is the best way to get React to use only one instance of the component and 'memorise field values'?

EDIT

I have added Redux to the example, but the store corresponding to the form within the Tab is destroyed the moment I switch away. Is there any other way to implement tabs in React that would hide the tab contents, instead of destroying them and re-creating them from scratch each time I navigate away?

like image 928
tonysepia Avatar asked Mar 03 '23 14:03

tonysepia


2 Answers

The solution to my problem was quite simple! If you don't want to destroy the component (remove it from DOM), you can simply hide it!

Instead of:

{value === 0 && <Tab1Contents/>}

Use:

<div style={{ display: value === 0? 'block': 'none'}}>
    <Tab1Contents/>
</div>
like image 82
tonysepia Avatar answered Apr 06 '23 15:04

tonysepia


It was already mentioned that you have to prevent your component from being removed from the DOM. The easiest solution with MUI5 TabPanel is in fact to just replace

{value === index && children}

with

{children}

that means your Tabpanel would look like that:

import * as React from "react";


const TabPanel= ({ children, value, index, ...other }) => {

  return (
    <div
      role="tabpanel"
      hidden={value !== index}
      id={`tabpanel-${index}`}
      aria-labelledby={`tab-${index}`}
      {...other}
    >
      {children}
      {/* {value === index && children} // This was removed */}
    </div>
  );
};

export default TabPanel;

No additional logic necessary as the hidden prop already takes care of the visibility aspect. This way your components should maintain their state!

like image 41
smarwin Avatar answered Apr 06 '23 14:04

smarwin