Brig
Brig

Reputation: 123

React Tabs onClick get index of selected Tab

I am new to React and I am trying to get the selected Tab and from a onClick event.

Below is my code along with output.

How would I implement the handleSelect function?

Here is my current code:

class Header extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value : 0};
  }

  getState(){
    return this.state.value;
  }

  setState(state){
    this.state = state;
  }

  handleSelect(index){
    console.log('Selected tab: ' + index);
  }

  render() {
    let selectedIndex = this.getState();

    return (
      <header className="header">
        <AppBar title="App Bar" />

        <Tabs>
          <Tab label="Core Courses" onClick={this.handleSelect(0)} />
          <Tab label="Capstone Requirement" onClick={this.handleSelect(1)}/>
          <Tab label="Computer Science Electives" onClick={this.handleSelect(2)}/>
          <Tab label="Support Courses" onClick={this.handleSelect(3)} />
        </Tabs>

      </header>
    );
  }
}

Here is the console log currently when rendered:

Selected tab: 0
Selected tab: 1
Selected tab: 2
Selected tab: 3

Upvotes: 3

Views: 27333

Answers (6)

zahra zamani
zahra zamani

Reputation: 1375

you can use tabs in https://material-ui.com/components/tabs/

in your code `

    class Header extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value : 0};
  }

  getState(){
    return this.state.value;
  }

  setState(state){
    this.state = state;
  }

  handleSelect(event, newValue) {
      
        this.setState({ value: newValue })
       

    }

  render() {
    let selectedIndex = this.getState();

    return (
      <header className="header">
        <AppBar title="App Bar" />

      <Paper square  >
    <Tabs value={this.state.value} indicatorColor="primary" textColor="primary" onChange={this.handleSelect}>

          <Tab label="Core Courses"  />
          <Tab label="Capstone Requirement" />
          <Tab label="Computer Science Electives"/>
          <Tab label="Support Courses"  />
        </Tabs>
 </Paper >
      </header>
    );
  }
}


    `

and yon can set onClick for each Tab

Upvotes: 0

Carlos G
Carlos G

Reputation: 9

This is the way I think is more readable, using a functional component with useState hook and material ui Tabs and Tab components.

You can have access to the current selected child tab index as an argument passed to the function handler provided to the onChange prop of the Tabs component.

    `const Header = ()=>{
         const[currentIndex,setCurrentIndex]=React.useState(0)

         const handleChange = (event, currentSelectedIndex) => 
               {  setCurrentIndex(currentSelectedIndex) };

          return (
              <Tabs
               value={currentIndex}
               onChange={handleChange}
             >
                   <Tab label="Core Courses"/>
                   <Tab label="Capstone Requirement"/>
                   <Tab label="Computer Science Electives"/>
                   <Tab label="Support Courses" />
              </Tabs>
                                )
                          }`

Upvotes: 0

Swapnil
Swapnil

Reputation: 2603

This is how I would do it:

class Header extends React.Component {
    constructor(props) {
        super(props);
        this.state = {selectedIndex : 0};
    }

    //Use arrow functions to avoid binding
    handleSelect = (index) => {
        this.setState({selectedIndex: index}, () => {
            console.log('Selected tab: ' + this.state.selectedIndex);
        })
    }

   render() {
        const {selectedIndex} = this.state

        return (
          <header className="header">
            <AppBar title="App Bar" />

              <Tabs>
                 <Tab label="Core Courses" onClick={() =>this.handleSelect(0)} />
                 <Tab label="Capstone Requirement" onClick={() => this.handleSelect(1)}/>
                 <Tab label="Computer Science Electives" onClick={() => this.handleSelect(2)}/>
                 <Tab label="Support Courses" onClick={() => this.handleSelect(3)} />
             </Tabs>

         </header>
      );
   }
}

Notice that I have removed the getState and setState functions. That is because in react you are supposed to set your state using the setState() function. Also notice that i console the new state in a callback (the second argument given to setState). This is because setState doesn't immediately change the state instead it creates a pending state transition. We can pass a callback to setState method which is called once the state has been changed.

Refer to react doc to get more understanding https://facebook.github.io/react/docs/react-component.html#setstate

Now lets move on to your getState function. You don't need a function to access the state of the component instead you can access it using this.state inside the render method. Also the component's state is never changed inside the render function and remains constant inside it that is why I think using const over let should be preferred.

Upvotes: 0

maheshiv
maheshiv

Reputation: 1858

You can use bind.

<Tab label="Core Courses1" onClick={this.handleSelect.bind(this, 0)} />
<Tab label="Core Courses2" onClick={this.handleSelect.bind(this, 1)} />
<Tab label="Core Courses3" onClick={this.handleSelect.bind(this, 2)} />

Upvotes: 0

yadhu
yadhu

Reputation: 15632

Multiple <Tab/> can be generated using Array.prototype.map:

class Header extends React.Component {
    constructor(props) {
        super(props);
    }

    // in ES6 we prefer to initialize state using the keyword 'static'
    static state = {
        value: 0,
    }

    // defined as an arrow fn so that 'this' inside handleSelect
    // is the 'this' of component class (lexical scoping)
    handleSelect = (index) => {
        console.log('Selected tab: ' + index);
        // this is how you update your state
        this.setState({ value: index });
    }

    render() {
        const me = this; 

        // you don't need a getter for Reading the value of state
        console.log(me.state);

        return (
            <header className="header">
                <AppBar title="App Bar" />
                <Tabs>
                    {
                        [
                        'Core Courses',
                        'Capstone Requirement',
                        'Computer Science Electives',
                        'Support Courses'
                        ].map((label, index) =>
                            <Tab
                                value={label}
                                key={index}
                                onClick={() => me.handleSelect(index)}
                            />
                        )
                    }
                </Tabs>
            </header>
        );
    }
}

Upvotes: 0

Eranga Kapukotuwa
Eranga Kapukotuwa

Reputation: 4952

Following code will add an "active" class to the selected tab. Hope you can manage it with css, if you have an "active" class inside the selected tab.

class Header extends React.Component {
  constructor(props) {
  super(props);
  this.state = {
    activeTab : 0
  };
  this.handleSelect = this.handleSelect.bind(this);
}

handleSelect(index){
  this.setState({
    activeTab: index
  });
}

render() {
  let selectedIndex = this.getState();

  return (
    <header className="header">
      <AppBar title="App Bar" />
      <Tabs>
        <Tab classsName={this.state.activeTab == 0 ? 'active' : ''} label="Core Courses" onClick={this.handleSelect(0)} />
        <Tab classsName={this.state.activeTab == 1 ? 'active' : ''} label="Capstone Requirement" onClick={this.handleSelect(1)}/>
        <Tab classsName={this.state.activeTab == 2 ? 'active' : ''} label="Computer Science Electives" onClick={this.handleSelect(2)}/>
        <Tab classsName={this.state.activeTab == 3 ? 'active' : ''} label="Support Courses" onClick={this.handleSelect(3)} />
    </Tabs>
  </header>
);

} }

Upvotes: 3

Related Questions