Tabs 仅在第一次激活时挂载 Tab 内容

IT技术 reactjs react-bootstrap
2021-05-05 13:11:18

我只想在第一次激活时加载选项卡内容,之后内容保留在 DOM 中

这就是我所拥有的

  <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>

它工作正常,但切换选项卡之间存在延迟,因为我拥有的内容非常大,我只想在选项卡第一次激活时呈现一次。

有没有办法实现这一目标?我正在使用react-bootstrap 0.30.10

3个回答

更新

显然mountOnEnter必须与 一起使用animation,否则它将无法按预期工作。我进行了更改,现在工作正常

旧答案

所以我想出了这个包装组件如下

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;

它似乎工作正常,但我认为这有点hacky,但这是我现在能想出的最好的。

这听起来像是 React 提供的“避免协调”选项的一个很好的用例。

这是文档中相关部分的链接。

本质上,有一个生命周期事件被称为shouldComponentUpdate默认为 true。当您将其更改为 false 时,它​​会告诉 React 不要通过标准的 Reconciliation 过程(即“差异”检查)运行组件。

与任何生命周期方法一样,您可以为其创建条件语句。

对于在第一次渲染后应该完全静态的组件,这真的是你所需要的:

class YourComponent extends React.Component {
  ...
  shouldComponentUpdate() {
    return false;
  }
  ...
}

但是,对于更一般的用例,您需要根据组件的 props 和/或状态编写条件语句:

class YourComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { 
        // Your state
    };
  }

  shouldComponentUpdate(nextProps, nextState) {
        // A conditional statement to determine whether
        //    this component should check for updates or not
  }

  render () {
    return (
        <div>
          {/* Your JSX*/}
        </div>
    )
  }

我不使用 React Boostrap 但我猜它是基于组件设计的,例如,渲染的内容使用 TabIndex 状态。仔细看看这个示例代码:

  renderActiveTabContent() {
    const { children } = this.props
    const { activeTabIndex } = this.state
    if (children[activeTabIndex]) {
      return children[activeTabIndex].props.children
    }
  }

所以每次 Tab 状态被索引时,内容组件都会呈现。

您可以使用https://github.com/reactjs/react-tabs作为您的解决方案,否则查看这些代码来编写一个简单的代码,组件渲染一次并通过display:样式属性显示/隐藏状态

希望它有帮助。