React add class active on selected tab

In this case, would be better move state management to parent component Tabs, and pass to child only props which you need to detect class name or set new state in parent

var Tab = React.createClass({
  render: function() {
    return <li 
      className={ this.props.isActive ? 'navigation--active': '' }
      onClick={ this.props.onActiveTab }
    >
      <p>{ this.props.content }</p>
    </li>
  }
});

var Tabs = React.createClass({
  getInitialState: function() {
    return { selectedTabId: 1 }
  },
  
  isActive: function (id) {
    return this.state.selectedTabId === id;
  },
  
  setActiveTab: function (selectedTabId) {
    this.setState({ selectedTabId });
  },
  
  render: function() {
    var total = this.props.data.points.total,
    	tabs = total.map(function (el, i) {
          return <Tab 
            key={ i }
            content={ el.name } 
            isActive={ this.isActive(el.id) } 
            onActiveTab={ this.setActiveTab.bind(this, el.id) }
          />
        }, this);
                
    return <ul className="navigation">
     { tabs }
    </ul>
  }
});

const data = {
  points: {
    total: [
      { id: 1, name: 'tab-1', text: 'text' },
      { id: 2, name: 'tab-2', text: 'text-2' },
      { id: 3, name: 'tab-3', text: 'text-2' }
    ]
  }
}

ReactDOM.render(
  <Tabs data={ data } />,
  document.getElementById('container')
);
.navigation {}

.navigation--active {
  color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="container"></div>

Necro poster here. Cool answer up above!

In any way, here is the 2018 upgrade answer with recompose and styled-components. You can even make a HOC out of it for a joyful reusability!

https://codesandbox.io/s/1826454zl7

import React from "react";
import ReactDOM from "react-dom";
import { compose, withState, withHandlers } from "recompose";
import styled from "styled-components";

const enhancer = compose(
  withState("selectedTabId", "setSelectedTabId", 1),
  withHandlers({
    isActive: props => id => {
      return props.selectedTabId === id;
    },
    setActiveTab: props => id => {
      props.setSelectedTabId(id);
    }
  })
);

const Tabs = enhancer(props => {
  return (
    <ul>
      {props.data.map((el, i) => {
        return (
          <Tab
            key={i}
            content={el.name}
            isActive={props.isActive(el.id)}
            onActiveTab={() => props.setActiveTab(el.id)}
          />
        );
      })}
    </ul>
  );
});

const Tab = props => {
  return (
    <StyledLi isActive={props.isActive} onClick={props.onActiveTab}>
      <p>{props.content}</p>
    </StyledLi>
  );
};

const StyledLi = styled.li`
  font-weight: ${({ isActive }) => (isActive ? 600 : 100)};
  cursor: pointer;
  font-family: Helvetica;
  transition: 200ms all linear;
`;

const data = [
  { id: 1, name: "tab-1", text: "text" },
  { id: 2, name: "tab-2", text: "text-2" },
  { id: 3, name: "tab-3", text: "text-2" }
];

const ExampleApp = () => <Tabs data={data} />;

ReactDOM.render(<ExampleApp />, document.getElementById("app"));

Basic idea is that you need to get selected index, map over the item on every click, compare selected index with all other indexes and return true to props of a needed component if the match is found.

Tags:

Reactjs