1

I had scanned the Tabs component of react-bootstrap, but it was not a good choice, it mounted all the tab once the Tabs Component did mounted. So I use the child route to make a Tabs Component.

I have three tabs. For Example, tabA, tabB, tabC.

Specially, tabA and tabB have the same UI, but they request the different API

<Route path="tabs" getComponent={ProfitReports.flag.detail.default}>
    <Route path="tabA" getComponent={tabAorB}/>
    <Route path="tabB" getComponent={tabAorB}/>
    <Route path="tabC" getComponent={tabC}/>
</Route>

....

class Tabs extends React.Component {
    render() {
        return (
            <Flex className="gm-tabs gm-paddingLR15">
                <IndexLink to="/tabs/tabA" className="tab" activeClassName="active">TabA</IndexLink>
                <Link to="/tabs/tabB" className="tab" activeClassName="active">TabB</Link>
                <Link to="/tabs/tabC" className="tab" activeClassName="active">TabC</Link>
            </Flex>
        );
    }
}

export default Tabs;

But it comes the problem.

When I Click the tabA link, it works, But when I Click the tabB link, that nothing happen except the url has changed. No request, no new component init

and I found the TabAorB component was not unmount, so I think maybe the problem was made here.

Requirement

I hope:

where I click the tabA link, it request the API1, and request the API2 after click the tabB link

3 Answers 3

0

You may have some conflict or config error with your routes. However, for me, using Router doesn't look like a clean solution for tabs. Here is tabs component that is used in a project with bootstrap 3:

import React from 'react';
import ReactDOM from 'react-dom';
import $ from 'jquery';


export default class Tabs extends React.Component {
  componentDidMount() {
    this.panelsContainer = $(ReactDOM.findDOMNode(this.refs.panelsContainer));
    this.tabsContainer = $(ReactDOM.findDOMNode(this.refs.tabsContainer));
    this.panels = this.panelsContainer.find('.panel-tab');
    this.tabs = this.tabsContainer.find('li');
    this.tabs.eq(0).addClass('active');
    this.panels.eq(0).css(this._styles.panelActive);
    this.panelsContainer.height(this.props.minHeight);
  }


  _handleClick(e) {
    const panel = $(ReactDOM.findDOMNode(this.refs[e.target.dataset.toggle]));
    const tab = $(e.target).parent();

    this.tabs.removeClass('active');
    tab.addClass('active');

    this.panelsContainer.height(panel.height());
    this.panels.css(this._styles.panel);
    panel.css(this._styles.panelActive);
  }

  _styles = {
    panel: {
      visibility: 'hidden',
      width: '100%',
      position: 'absolute',
      background: '#fff',
      border: '1px solid #ddd',
      borderTop: 'none',
    },
    panelActive: {
      visibility: 'visible',
      top: 0,
      left: 0,
    },
    panelsContainer: {
      position: 'relative',
    },
  };


  render() {
    let count = 0;

    const tabs = (
      <ul className="nav nav-tabs" ref="tabsContainer">
        {this.props.tabsNavItems.map((tab, key) =>
          <li key={key}><a href="javascript:void(0)" onClick={this._handleClick.bind(this)} data-toggle={++count}>{tab.tag}</a></li>
        )}
      </ul>
    );

    count = 0;

    const tabPanes = (
      <div style={this._styles.panelsContainer} ref="panelsContainer">
        { React.Children.map(this.props.children, (child) =>
          <div className="panel-tab" style={this._styles.panel} ref={++count}>
            { child }
          </div>
        )}
      </div>
    );

    return (
      <div >
          { tabs }
          { tabPanes }
      </div>
    );
  }
}

Tabs.propTypes = {
  tabsNavItems: React.PropTypes.array.isRequired,
};

Then you can use it like this:

 _tabsNavItems = [
    { tag: 'Tab A' },
    { tag: 'Tab B' },
 ]
...

<Tabs tabsNavItems={this._tabsNavItems} minHeight={375}>
 <TabAContent />
 <TabBContent />
</Tabs>
Sign up to request clarification or add additional context in comments.

1 Comment

But it seems no different to the Tab component of React-bootstrap.They mount all the content when the Tab component has been mounted.It's really a big waste.
0

I solve this problem with requesting the api in the shouldComponentUpdate

1 Comment

But Actually it's a bad idea that requesting the api in the shouldComponentUpdate
0

I stumbled across this today, it seems they have now fixed this issue at the Tabs of react-bootstrap, so you don't have to use react-router for this.

You should pass the property unmountOnExit on your Tabs component, and your components will mount only when they are active.

References:

Comments

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.