Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React add class active on selected tab

Tags:

reactjs

I have the following:

var Tab = React.createClass({
    getInitialState: function(){
        return {
          selected:''
        }
    },
    activateTab: function(e) {
        e.preventDefault();
        $('.navigation--active').removeClass('navigation--active');
        this.setState({selected  : true});
    },
    render: function() {
        var isActive = this.state.selected === true ? 'navigation--active': '';
        return (
            <li onClick={this.activateTab} className={isActive}>
                <p>
                    {this.props.content}
                </p>
            </li>
        );
    }
});

var Tabs = React.createClass({
    render: function() {
        var tabs = [],
            total = this.props.data.points.total,
            handleClick = this.handleClick;
        total.forEach(function(el, i){
            tabs.push(
                <Tab content = {el.name} 
                     key = {i}/>
            );
        });
        return (
            <ul className="navigation">
                {tabs}
            </ul>
        );
    }
});

however it only works when you click once on every tab, if you click the second time on the same tab the class doesn't get added anymore

like image 247
Aessandro Avatar asked Jul 18 '16 12:07

Aessandro


1 Answers

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.

like image 188
Serge Nikolaev Avatar answered Oct 07 '22 01:10

Serge Nikolaev