How to add if else inside the Tabs in react bootstrap

Viewed 1890

I try to execute following code but I got some error. Error : ReactBootstrap: The Tab component is not meant to be rendered! It's an abstract component that is only valid as a direct Child of the Tabs Component. For custom tabs components use TabPane and TabsContainer directly.


import { Row, Col, Tabs, Tab } from "react-bootstrap";
import One from "../One.jsx";
//One,Two .. etc There are more

render(
  <Tabs>
        <Tab eventKey={1} title="Tab 1"><One/></Tab>                           
        <Tab eventKey={2} title="Tab 2"><Two/></Tab>                           
        <Tab eventKey={3} title="Tab 3"><Three/></Tab>   
  {this.state.type === type && (
        <Tab eventKey={4} title="Tab 4"><Four/></Tab>                           
        <Tab eventKey={5} title="Tab 5"><Five/></Tab>                           
        <Tab eventKey={6} title="Tab 6"><Six/></Tab>  
 )}
  </Tabs>
)

3 Answers

I don't think you can construct new Tab components like that using conditional rendering. As stated in the error message, you can use Tab.Container & Tab.Pane to create your customs Tabs.

Reference to the docs:

For more complex layouts the flexible TabContainer, TabContent, and TabPane components along with any style of Nav allow you to quickly piece together your own Tabs component with additional markup needed.

Example implementation of Tabs contruction with conditional rendering:

return (
  <Tab.Container defaultActiveKey={1}>
    <Nav variant="pills" className="flex-column">
      <Row>
        <Nav.Item>
          <Nav.Link eventKey={1}>Tab 1</Nav.Link>
        </Nav.Item>
        <Nav.Item>
          <Nav.Link eventKey={2}>Tab 2</Nav.Link>
        </Nav.Item>
        <Nav.Item>
          <Nav.Link eventKey={3}>Tab 2</Nav.Link>
        </Nav.Item>
        {this.state.type === type && (
          <>
            <Nav.Item>
              <Nav.Link eventKey={4}>Tab 4</Nav.Link>
            </Nav.Item>
            <Nav.Item>
              <Nav.Link eventKey={5}>Tab 5</Nav.Link>
            </Nav.Item>
            <Nav.Item>
              <Nav.Link eventKey={6}>Tab 6</Nav.Link>
            </Nav.Item>
          </>
        )}
      </Row>
    </Nav>

    <Tab.Content>
      <Tab.Pane eventKey={1} title="Tab 1">
        1
      </Tab.Pane>
      <Tab.Pane eventKey={2} title="Tab 2">
        2
      </Tab.Pane>
      <Tab.Pane eventKey={3} title="Tab 3">
        3
      </Tab.Pane>

      {this.state.type === type && (
        <>
          <Tab.Pane eventKey={4} title="Tab 4">
            4
          </Tab.Pane>
          <Tab.Pane eventKey={5} title="Tab 5">
            5
          </Tab.Pane>
          <Tab.Pane eventKey={6} title="Tab 6">
            6
          </Tab.Pane>
        </>
      )}
    </Tab.Content>
  </Tab.Container>
);

Edit currying-dream-6xdqj

In fact, if you view the components on React Dev Tools, you will notice that the "Tab" component in fact is not actually rendered when using Tabs & Tab combo - hence they defined it as "abstract" component

enter image description here


Alternatively, if you must use Tabs & Tab JSX combo, then you are going to have to implement the condition on the entire Tabs rendering - not just a section of it. You can find an example here: https://codesandbox.io/s/beautiful-pond-quc2b?file=/src/App.js

I found this solution by accident.

I used to declare component's name as Tab without import from 'react-bootstrap' and using JSX condition rendering not any problem

But when I changed component's name to another, I found error from 'react-bootstrap' and my JSX condition rendering didn't work anymore cause 'react-bootstrap' wont accept JSX shorthand fragment or any.

So I declare empty component for handle error and using <>...</> in JSX condition rendering and everything works for me.

import React from "react";
import { Tabs } from "react-bootstrap";
    
const Tab = () => {
  return <></>; 
};
    
export const App = (props) => {
  return(
    <Tabs>
      <Tab eventKey={1} title="Tab 1"><One/></Tab>                           
      <Tab eventKey={2} title="Tab 2"><Two/></Tab>                           
      <Tab eventKey={3} title="Tab 3"><Three/></Tab>   
      {props.type === type && (
        <>
          <Tab eventKey={4} title="Tab 4"><Four/></Tab>                           
          <Tab eventKey={5} title="Tab 5"><Five/></Tab>                           
          <Tab eventKey={6} title="Tab 6"><Six/></Tab>  
        </>
      )}
    </Tabs>
  )
}

On top is not good practice but it's easy to declare condition.

In case you want to do with better practice use this instead.

import React from "react";
import { Tabs, Tab } from "react-bootstrap";
        
export const App = (props) => {
  return(
    <Tabs>
      <Tab eventKey={1} title="Tab 1"><One/></Tab>                           
      <Tab eventKey={2} title="Tab 2"><Two/></Tab>                           
      <Tab eventKey={3} title="Tab 3"><Three/></Tab>   
      {props.type === type && <Tab eventKey={4} title="Tab 4"><Four/></Tab>}
      {props.type === type && <Tab eventKey={5} title="Tab 5"><Five/></Tab>}
      {props.type === type && <Tab eventKey={6} title="Tab 6"><Six/></Tab>}
    </Tabs>
  )
}

You can refer to the following official documentation. It is explained very well. https://reactjs.org/docs/conditional-rendering.html

Here is a sample code which I took from documentation. Hope this will clear your concept.

 render() {
const isLoggedIn = this.state.isLoggedIn;
let button;
if (isLoggedIn) {
  button = <LogoutButton onClick={this.handleLogoutClick} />;
} else {
  button = <LoginButton onClick={this.handleLoginClick} />;
}

return (
  <div>
    <Greeting isLoggedIn={isLoggedIn} />
    {button}
  </div>
);

}

Related