最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Reactjs material ui prevent re-render tabs on enter - Stack Overflow

programmeradmin6浏览0评论

I have built a material-ui based UI containing tabs in reactJS. Anytime a tab is selected, the content under that tab reloads which is causing a major performance issue because I am displaying an iFrame under one those tabs. I tried to use React.memo to ensure that the screen does not re-render because there is no change in the props but it still does.

Here is the code -

Code sandbox link

Is there a way, that once the iFrame is loaded for the first time and I switch between tabs, the iframe does not get re-rendered again?

I have built a material-ui based UI containing tabs in reactJS. Anytime a tab is selected, the content under that tab reloads which is causing a major performance issue because I am displaying an iFrame under one those tabs. I tried to use React.memo to ensure that the screen does not re-render because there is no change in the props but it still does.

Here is the code -

Code sandbox link

Is there a way, that once the iFrame is loaded for the first time and I switch between tabs, the iframe does not get re-rendered again?

Share Improve this question edited Apr 8, 2020 at 10:18 Niraj asked Apr 8, 2020 at 9:27 Niraj Niraj 3732 gold badges5 silver badges26 bronze badges 2
  • Actually using useMemo does not render the ponent twice, HTML reloads the source of your iFrame on ponent mount. I've made a sandbox with useMemo and put a console.count there, you can check it's rendered only once codesandbox.io/s/material-demo-5tigs?file=/demo.js – Sabbin Commented Apr 8, 2020 at 9:48
  • 1 Thanks Sabbin, but I needed the state of the poent to be maintained after you switch the tab. If we useMemo and start the video in one tab and switch to the other tab and then switch back, the video gets loaded again from beginning. I wanted to avoid that – Niraj Commented Apr 8, 2020 at 11:08
Add a ment  | 

2 Answers 2

Reset to default 15

You check if the value of the current tab equals the index of the current tab, and only if they are equal you display the content.
Instead - just keep the content and have the Typography ponent control the visibility of it's content (which you already have, using the hidden inside the Typography ponent.

<Typography
  ponent="div"
  role="tabpanel"
  hidden={value !== index}
  id={`simple-tabpanel-${index}`}
  aria-labelledby={`simple-tab-${index}`}
  {...other}
>
  {<Box p={3}>{children}</Box>}
</Typography>

Note that the content will be rendered, so if you have a lot of content inside/requests to the backend/etc - all of those will be part of your DOM, even if you don't see them.

TypeScript solution:

  1. Wrap the tab display ponent in a memo() function call
  2. Wrap the display ponent with the control logic (<div style={...})
  3. Tab change won't re-render the DOM anymore; size of tab content naturally flows by tab display ponent size. Flushing/update can be triggered by state changes in tab display ponent.

Example code:

  const SomeTabDisplayComponent = memo(() => {
      return <div>Whatever the tab displays</div>
  })


  const getVisibilityStyle = (hiddenCondition: boolean): any => {
      if (hiddenCondition) {
          return {
              visibility: 'hidden',
              height: 0,
          };
      }
      return {
          visibility: 'visible',
          height: 'inherit',
      };
  };

  <div style={getVisibilityStyle(value !== index)}>
      <SomeTabDisplayComponent />
  </div>

This solution has many advantages over the prev. answer. It doesn't use another ponent; doesn't mis-use "Typography" (<p> tag is not meant to include block content! Doing this is bad for SEO and accessibility etc.; violates web standards.); It doesn't depend on Typography's it's internal "hidden" implementation (if that one changes in the future, the upper solution will break) and it gives full control over when the re-render/DOM flush happens.

发布评论

评论列表(0)

  1. 暂无评论