sshussain270
sshussain270

Reputation: 1865

Lazy loading in MUI causes useEffect to not work

I am implementing tabs interface from React's MUI library (https://mui.com/material-ui/react-tabs/#fixed-tabs)

Following is my code:

import * as React from 'react';
import PropTypes from 'prop-types';
import SwipeableViews from 'react-swipeable-views';
import { useTheme } from '@mui/material/styles';
import AppBar from '@mui/material/AppBar';
import Tabs from '@mui/material/Tabs';
import Tab from '@mui/material/Tab';
import Typography from '@mui/material/Typography';
import Box from '@mui/material/Box';

function TabPanel(props) {
  const { children, value, index, ...other } = props;

  return (
    <div
      role="tabpanel"
      hidden={value !== index}
      id={`full-width-tabpanel-${index}`}
      aria-labelledby={`full-width-tab-${index}`}
      {...other}
    >
      {value === index && (
        <Box sx={{ p: 3 }}>
          <Typography>{children}</Typography>
        </Box>
      )}
    </div>
  );
}

TabPanel.propTypes = {
  children: PropTypes.node,
  index: PropTypes.number.isRequired,
  value: PropTypes.number.isRequired,
};

function a11yProps(index) {
  return {
    id: `full-width-tab-${index}`,
    'aria-controls': `full-width-tabpanel-${index}`,
  };
}

export default function FullWidthTabs() {
  const theme = useTheme();
  const [value, setValue] = React.useState(0);

  const handleChange = (event, newValue) => {
    setValue(newValue);
  };

  const handleChangeIndex = (index) => {
    setValue(index);
  };

  return (
    <Box sx={{ bgcolor: 'background.paper', width: 500 }}>
      <AppBar position="static">
        <Tabs
          value={value}
          onChange={handleChange}
          indicatorColor="secondary"
          textColor="inherit"
          variant="fullWidth"
          aria-label="full width tabs example"
        >
          <Tab label="Item One" {...a11yProps(0)} />
          <Tab label="Item Two" {...a11yProps(1)} />
        </Tabs>
      </AppBar>
      <SwipeableViews
        axis={theme.direction === 'rtl' ? 'x-reverse' : 'x'}
        index={value}
        onChangeIndex={handleChangeIndex}
      >
        <TabPanel value={value} index={0} dir={theme.direction}>
          <input type="text" />
        </TabPanel>
        <TabPanel value={value} index={1} dir={theme.direction}>
          <input type="text" />
        </TabPanel>
      </SwipeableViews>
    </Box>
  );
}

The two tabs' body contain two text fields <input type="text" />.

The problem is that when I move between tabs, I lose the data user has entered in the text fields.

For example,if I add something to Item One tab text field and then go to Item Two tab and then come back to Item One tab, the data i entered to the text field has disappeared.

Is that happening because of lazy loading? How do I fix it?

Upvotes: 1

Views: 1372

Answers (1)

Lakruwan Pathirage
Lakruwan Pathirage

Reputation: 657

That Because of the Material UI Tab Component behavior. When You switching the tabs, the rendered component get removed and new instance created for the new visited tab. I Have seen in the material ui git repository, mention other developers this as bug and I wonder that they didn't fixed this out yet.

So basically you have small quick solution have to be done. The main idea of this is ,You don't need to re render your switching component again and again.

Step1 First thing don't Use TabPanel component. You have to save your current values in the state.

Step2 create a class in css with display none

ex:

.none{
display:none;
}

Step3 when the index of the current tab index is same as the index of your tab,add that .none class to it.

Upvotes: 1

Related Questions