Reputation: 81
I need some help switching between tabs. I’ve attached an image to help demonstrate what I mean. I’ve tried many different ways to accomplish this, but I’m stuck. Allow me to explain:
I have created a json file that holds these 5 tabs in an array of objects. Each one has an id and a name. I am dynamically creating each tab component by mapping through this array within a parent component (the navbar component). The reason I’m doing it this way is so I can easily add more tabs to my .json file later and it’ll automatically add more tab components, without the need to code it in. I want a dynamic solution, not a static one.
[
{
"id": 0,
"name": "Home"
},
{
"id": 1,
"name": "About"
},
{
"id": 2,
"name": "Skills"
},
{
"id": 3,
"name": "Projects"
},
{
"id": 4,
"name": "Games"
}
]
export default class Navigation extends React.Component {
buildTabs = (tab) => {
return(
<Tab
key={tab.id}
id={tab.id}
name={tab.name}
/>
);
}
render() {
return(
<div style={style}>
{TabJSON.map(this.buildTabs)}
</div>
);
}
}
I have tried to set a selected state within the tab component itself, but when I click a new tab, the previous one doesn’t disappear. It will just toggle them on individually, which isn’t what I want. I would like them to toggle selected and then remove that state from the others, just like a tab is supposed to work.
export default class Tab extends React.Component {
state = {
selected: this.props.id === 0 ? 'selected' : ''
}
tabClicked = (tab) => {
this.setState({
selected: 'selected'
});
}
render() {
return(
<div
id={this.props.id}
className={`tab ${this.state.selected}`}
onClick={this.tabClicked}
>{this.props.name}
</div>
);
}
}
I have tried to manage this state from the parent component (the navbar) so I can communicate between the sibling tab components, but I run into another issue. The components all get selected on or off together, instead of independently no matter which one I click.
Sorry for the long message, I hope someone can help me out.
Upvotes: 2
Views: 8508
Reputation: 599
Your selected state must be inside a parent Component. For example, you could add a onClick prop function to your Tab:
export default class Tab extends React.Component {
render() {
const { id, onClick, selectedTab } = this.props;
return (
<div
id= {id}
className = {`tab ${id === selectedTab ? 'selected' : ''}`}
onClick = {onClick}
>
{ this.props.name }
</div>
);
}
}
And then control the Selected tab from your parent component (Navigation), passing the current selected Tab for each one, like this:
export default class Navigation extends React.Component {
state = {
selectedTab: 0
}
onClickTab = id => () => {
this.setState({ selectedTab: id });
}
buildTabs = (tab) => {
return(
<Tab
key={tab.id}
id={tab.id}
name={tab.name}
onClick={this.onClickTab(tab.id)}
selectedTab={this.state.selectedTab}
/>
);
}
render() {
return(
<div style={style}>
{TabJSON.map(this.buildTabs)}
</div>
);
}
}
Upvotes: 1