Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to lazy mount Material UI tab panels or to know when a tab panel is visible?

I'm using Material UI tabs to select between three TabPanels. Specifically, I'm using the Simple Tabs Example.

The component in my second tab needs access to such fields and methods as elem.offsetHeight and elem.getClientRects() to adjust the layout. Unfortunately these display-based things are zero or empty until the component in the panel displays. All the panels mount right away, but the second panel isn't visible on mounting, so my layout adjustments don't work when I try to run them during the mount.

I think what I need is either of two things:

  1. Some way to lazy-load the contents of my tab panels. (This solution would probably be best, since the second and third panels require network calls, and makes no sense to make such a call until the panel is required.)

  2. Some way to know when the contents of the panel is finally displayed so that the code can trigger the layout adjustments.

Another solution would be to set a timeout to check periodically (say every 100 ms) whether elem.getClientRects() produces a list with any elements, but that seems rather hacky.


Addendum

I'm sorry my written description wasn't clearer. Inside my SimpleTabs component:

  <TabPanel value={value} index={0}>
    <About/>
  </TabPanel>
  <TabPanel value={value} index={1}>
    <ByRossPage/>
  </TabPanel>
  <TabPanel value={value} index={2}>
    <ByChapter/>
  </TabPanel>

The <ByRossPage/> component contains the getPage() method that accesses elem.offsetHeight and elem.getClientRects(). This method is called from the component's constructor.

like image 386
JohnK Avatar asked Aug 12 '19 17:08

JohnK


People also ask

How do you use a tab panel?

Keyboard Interaction The user reaches the tabbed panel component by pressing the tab key until the active tab title receives focus. left arrow - with focus on a tab, pressing the left arrow will move focus to the previous tab in the tab list and activate that tab.


1 Answers

I figured out how to get the contents of the TabPanel to lazy load. I modified the TabPanel functional component like this:

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

  return (
    <Typography
      component="div"
      role="tabpanel"
      hidden={value !== index}
      id={`simple-tabpanel-${index}`}
      aria-labelledby={`simple-tab-${index}`}
    >
      <Box p={3}>{value === index && children}</Box>
    </Typography>
  );
}

The only changed line is this one:

 <Box p={3}>{value === index && children}</Box>

which had been this

<Box p={3}>{children}</Box>
like image 200
JohnK Avatar answered Oct 14 '22 07:10

JohnK