Renders a tabbed menu and view component.
- Define a
TabItem
component, pass it to theTab
and remove unnecessary nodes expect forTabItem
by identifying the function’s name inprops.children
. - Use the
React.useState()
hook to initialize the value of thebindIndex
state variable toprops.defaultIndex
. - Use
Array.prototype.map
on the collected nodes to render thetab-menu
andtab-view
. - Define
changeTab
, which will be executed when clicking a<button>
from thetab-menu
. changeTab
executes the passed callback,onTabClick
and updatesbindIndex
, which in turn causes a re-render, evaluating thestyle
andclassName
of thetab-view
items andtab-menu
buttons according to theirindex
.
代码实现
.tab-menu > button {
cursor: pointer;
padding: 8px 16px;
border: 0;
border-bottom: 2px solid transparent;
background: none;
}
.tab-menu > button.focus {
border-bottom: 2px solid #007bef;
}
.tab-menu > button:hover {
border-bottom: 2px solid #007bef;
}
使用样例
function TabItem(props) {
return <div {...props} />;
}
function Tabs(props) {
const [bindIndex, setBindIndex] = React.useState(props.defaultIndex);
const changeTab = newIndex => {
if (typeof props.onTabClick === 'function') props.onTabClick(newIndex);
setBindIndex(newIndex);
};
const items = props.children.filter(item => item.type.name === 'TabItem');
return (
<div className="wrapper">
<div className="tab-menu">
{items.map(({ props: { index, label } }) => (
<button onClick={() => changeTab(index)} className={bindIndex === index ? 'focus' : ''}>
{label}
</button>
))}
</div>
<div className="tab-view">
{items.map(({ props }) => (
<div
{...props}
className="tab-view_item"
key={props.index}
style={{ display: bindIndex === props.index ? 'block' : 'none' }}
/>
))}
</div>
</div>
);
}
ReactDOM.render(
<Tabs defaultIndex="1" onTabClick={console.log}>
<TabItem label="A" index="1">
Lorem ipsum
</TabItem>
<TabItem label="B" index="2">
Dolor sit amet
</TabItem>
</Tabs>,
document.getElementById('root')
);