10

I have a react application using material-ui to create tabs.

<div className={classes.root}>
  <AppBar position="static">
    <Tabs value={value} onChange={handleChange}>
      <Tab label="Item One" />
      <Tab label="Item Two" />
      <Tab label="Item Three" />
    </Tabs>
  </AppBar>
  {value === 0 && <TabContainer id={1}>Item One</TabContainer>}
  {value === 1 && <TabContainer id={2}>Item Two</TabContainer>}
  {value === 2 && <TabContainer id={3}>Item Three</TabContainer>}
</div>

Edit Material-UI Tabs

The TabContainer is a functional component and does some heavy computation.
Is it possible to prevent TabContainer from re-rendering when switching between tabs?

Update:
Check my answer for a solution with React functional components and css classes.

2 Answers 2

9

Update/Partial Solution:
With the below code (based on Rahul Jain's answer) using css classes to display the active TabContainer, the memoized functions seems to be really memoized.

    const useTabContainerStyles = makeStyles((theme: Theme) =>  createStyles({
        root: {
          padding: 8 * 3
        },
        tabcontainerInActive: {
          display: "none"
        }
      })
    );

    function TabContainer(props: TabContainerProps) {
      const styles = useTabContainerStyles({});
      console.log("In TabContainer");
      const doubleValue = useMemo(() => double(props.id), [props.id]);
      return (
        <Typography
          id={props.id.toString()}
          component="div"
          className={classnames(styles.root, {
            [styles.tabcontainerInActive]: !props.active
          })}
        >
          {props.children + " " + doubleValue}
        </Typography>
      );
    }

    export default function SimpleTabs() {
      const classes = useStyles({});
      const [selectedTab, setSelectedTab] = React.useState(0);

      function handleChange(event: React.ChangeEvent<{}>, newValue: number) {
        setSelectedTab(newValue);
      }

      return (
        <div className={classes.root}>
          <AppBar position="static">
            <Tabs value={selectedTab} onChange={handleChange}>
              <Tab label="Item One" />
              <Tab label="Item Two" />
              <Tab label="Item Three" />
            </Tabs>
          </AppBar>
          {/*  */}
          <TabContainer id={0} active={selectedTab === 0}>
            Item One
          </TabContainer>
          <TabContainer id={1} active={selectedTab === 1}>
            Item Two
          </TabContainer>
          <TabContainer id={2} active={selectedTab === 2}>
            Item Three
          </TabContainer>
        </div>
      );
    }
Sign up to request clarification or add additional context in comments.

4 Comments

I'd recommend not doing this. It would be easier to just have the default container CSS class have display: none then have a class (e.g. tab-container--active) with the style display: block that gets added when selectedTab === index. No re-rendering, easier to test and more intuitive for anyone else looking at the code.
@Joe updated the code use CSS classes like you suggested.
@KiranMohan tried implementing your soultion, but no luck. On click of the tab each time tab container is re-rendered.
What is double?
6

In order to prevent TabContainer from re-rendering. You have to

  1. Render all TabContainer data at once instead of rendering based on value.
  2. You have to play with CSS and have to display only that tab which is currently active.
  3. Also you can make your component as PureComponent or you can override shouldComponentUpdate() lifecycle method to stop extra re-rendering of your react component.

2 Comments

i had already tried your suggestion 1 + 2 and it didn't work.
Using your suggestion I was able to get this working with react hooks and functional components. Check my update.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.