faksu3442
faksu3442

Reputation: 329

React MUI Tab component cause re-render and remove child states

We are trying to design a Tab Page using React MUI. We want each Tab to have a child component in it. When we add these children components to a single page without Tab, there is no problem, but when we add them to the Tab and TabPanel components of the MUI, we have a re-render problem. When switching from one tab to another tab, all fields and states in the previous tab are deleted.

I am also adding an example of this.

TabPage component :

export default function LabTabs() {
  const [value, setValue] = React.useState('1');

  const handleChange = (event: React.SyntheticEvent, newValue: string) => {
    setValue(newValue);
  };

  return (
    <Box sx={{ width: '100%', typography: 'body1' }}>
      <TabContext value={value}>
        <Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
          <TabList onChange={handleChange} aria-label="lab API tabs example">
            <Tab label="Item One" value="1" />
            <Tab label="Item Two" value="2" />
            <Tab label="Item Three" value="3" />
          </TabList>
        </Box>
        <TabPanel value="1">
          <Deneme />
        </TabPanel>
        <TabPanel value="2">Item Two</TabPanel>
        <TabPanel value="3">Item Three</TabPanel>
      </TabContext>
    </Box>
  );
}

Child component :

export default function Deneme() {
  const [value, setValue] = React.useState('1');


  const handleChange = (event: React.SyntheticEvent, newValue: string) => {
    setValue(newValue);
  };

  const [someChecked, setsomeChecked] = React.useState(false);
  const someChanged = (event: React.ChangeEvent<HTMLInputElement>) => {
      setsomeChecked(event.target.checked);
  };

  return (
         <FormControlLabel
                    label="Some Check Name"
                    control={
                        <Checkbox
                            checked={someChecked}
                            onChange={someChanged}
                            inputProps={{ "aria-label": "primary checkbox" }}
                        />}
                />
  );
}

And you can see the problem in StackBlitz, when you check the field that in first tab, and then switch the second tab and come back first tab, checkbox is resetting and the "someChecked" state is revert to default value.

https://stackblitz.com/edit/react-iari77?file=demo.tsx

So I can't see the problem, if we do not use the child component there is no problem, but we have to the use..

Upvotes: 2

Views: 7960

Answers (3)

Danilson Kayumbuca
Danilson Kayumbuca

Reputation: 1

Turn the TabPanel and the main component separated. In this way the issue will be fixed.

const TabPanel = (props) => {...}
const MainComponent = () =>{.... import the TabPanel, and the tabs}

React MUI

Upvotes: -2

faksu3442
faksu3442

Reputation: 329

I found the solution. I'm sharing it here for those who have this problem in the future.

We fixed the problem with the CSS trick. We set the display:none style to the condition and that way there was no problem of unmount/mount and re-render.

Sample code :

<TabPanel value={value}>
  {props.tabItems.map((item) =>  
    {return 
      <div style={{ display: item.value == value ? 'block' : 'none' }}> 
        {item.content}
      </div>
    })} 
</TabPanel>

Upvotes: 7

Kavindu Vindika
Kavindu Vindika

Reputation: 2737

That's the actual behavior when you're managing relevant state in child tab component. In order to persist your someChecked state of each child component, you've to manage them inside the parent component LabTabs.

With your current implementation, when you're moving from one tab to other tab, what actually happens is your previous tab component gets unmounted and next tab component gets mounted. As a result, all the state resides in your previous tab gets removed. That's why it seems state is removed, when you move back to your previous tab.

To avoid that manage state inside the parent component and pass them to the child components as props.

Upvotes: 0

Related Questions