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.