I’m trying to make a tabs component. TabsSwitcher and TabsPanel must be separate components so they could be used anywhere in DOM, e.g. TabsSwitcher doesn’t have to be followed
The React docs cover this in detail in "Communicate Between Components" and "Multiple Components". The gist is that the parent should pass a function as a prop to the child, and the child should call that function as a callback when it needs to:
var TabsExample = React.createClass({
handleTabClick: function(item) {
// Do something with item, maybe set it as active.
},
render: function() {
var tabs = [
{title: 'first', content: 'Content 1'},
{title: 'second', content: 'Content 2'}
];
return <div>
<TabsSwitcher items={tabs} onTabClick={this.handleTabClick}/>
<TabsContent items={tabs}/>
</div>;
}
});
var TabsSwitcher = React.createClass({
render: function() {
var items = this.props.items.map(function(item) {
return <a onClick={this.onClick.bind(this, item)}>{item.title}</a>;
}.bind(this));
return <div>{items}</div>;
},
onClick: function(item) {
this.props.onTabClick(item);
}
});
For the TabsContent
component, you should move the tabs
into the TabsExample
state so React can automatically re-render for you when they change. Since TabsSwitcher
and TabsContent
are passed the tabs in the render method, React knows they are dependent on the tabs and will re-render when the state changes:
var TabsExample = React.createClass({
getInitialState: function() {
return {
activeTabId: 1,
tabs: [
{title: 'first', content: 'Content 1', id: 1},
{title: 'second', content: 'Content 2', id: 2}
]
};
};
handleTabClick: function(item) {
// Call `setState` so React knows about the updated tab item.
this.setState({activeTabId: item.id});
},
render: function() {
return (
<div>
<TabsSwitcher items={this.state.tabs}
activeItemId={this.state.activeTabId}
onTabClick={this.handleTabClick}/>
<TabsContent items={this.state.tabs}
activeItemId={this.state.activeTabId}/>
</div>
);
}
});