Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tabs only mount Tab content on the first time it becomes active

I would like to load the tab content only on the first time it becomes active, after that the content stays in the DOM

This is what I have

  <Tabs defaultActiveKey={1} animation={false} id="my-tabs" mountOnEnter unmountOnExit>
    <Tab eventKey={1}>
      <div>content1</div>
    </Tab>
    <Tab eventKey={2}>
      <div>content1</div>
    </Tab>
  </Tabs>

it works fine, but there is a lag between switching tabs, since the content I have is quite large and I would like to render it only once, on the first time the tab becomes active.

Is there a way to achieve that? I'm using react-bootstrap 0.30.10

like image 511
lightbringer Avatar asked Jun 28 '17 02:06

lightbringer


People also ask

How do you know which tab is active in react JS?

You can use the useIsFocused hook. import { useIsFocused } from "@react-navigation/native"; Usage: In each of the tab screens that you want to detect if they are the currently active or focused. Save this answer.

How do I turn off tabs in react?

Disabled and Invisible Tabs (React) You can disable or hide individual tabs in the TabPanel control using the Tab's isDisabled and isVisible properties. Invisible and disabled tabs cannot be selected by the user.

How do you make dynamic tabs in react JS?

You can add dynamic tabs by reusing the content using React template. Tabs can be added dynamically by passing array of items and index value to the addTab method. Content reuse can be achieved by using the following steps: Declare a template within the function returns jsx element.


1 Answers

UPDATE:

apparently mountOnEnter must be used with animation, otherwise it will not work as intended. I made the change and it works fine now

Old answer:

so I have come up with this wrapping component as follow

class TabsLazyLoad extends Component {

  constructor(props) {
    super(props);
    this.state = this.getInitialState();
    this.handleSelect = this.handleSelect.bind(this);
  }

  getInitialState() {
    return {
      key: this.props.key || this.props.defaultActiveKey,
      rendered: [],
    };
  }

  addRenderedTab(key) {
    const newState = _.cloneDeep(this.state);
    newState.rendered.push(key);
    this.setState(newState);
  }

  handleSelect(key) {
    this.setState({ key });
  }

  render() {
    return (
      <Tabs activeKey={this.state.key} onSelect={this.handleSelect} {...this.props}>
        {_.map(this.props.children, (tabComponent) => {
          if (_.includes(this.state.rendered, tabComponent.props.eventKey)) {
            return tabComponent;
          }
          if (tabComponent.props.eventKey === this.state.key) {
            this.addRenderedTab(this.state.key);
          }

          // if it's not rendered, return an empty tab
          const emptyTab = _.cloneDeep(tabComponent);
          emptyTab.props.children = null;
          return emptyTab;
        })}
      </Tabs>
    );
  }
}

TabsLazyLoad.propTypes = Tabs.propTypes;

It seems to be working fine, but I reckon this is a bit hacky, but it's the best I can come up with for now.

like image 182
lightbringer Avatar answered Nov 15 '22 07:11

lightbringer