Update tabs to Hooks

This commit is contained in:
Angelos Chalaris
2019-02-12 21:10:05 +02:00
parent a6cb089ed4
commit f485e78339
3 changed files with 81 additions and 115 deletions

View File

@ -1,10 +1,11 @@
### Tab
Renders a tabbed menu and view component.
Define `TabItem` as a middleware, pass it to the `Tab` and remove unnecessary nodes expect for `TabItem` by identifying the function's name in `props.children`.
Define a `TabItem` component, pass it to the `Tab` and remove unnecessary nodes expect for `TabItem` by identifying the function's name in `props.children`.
Use the `React.useState()` hook to initialize the value of the `bindIndex` state variable to `props.defaultIndex`.
Use `Array.prototype.map` on the collected nodes to render the `tab-menu` and `tab-view`.
Define `changeTab`, which will be executed when clicking a `<button>` from the `tab-menu`.
`changeTab` executes the passed callback, `onTabClick` and updates `state.bindIndex`, which in turn causes a re-render, evaluating the `style` and `className` of the `tab-view` items and `tab-menu` buttons according to their `index`.
`changeTab` executes the passed callback, `onTabClick` and updates `bindIndex`, which in turn causes a re-render, evaluating the `style` and `className` of the `tab-view` items and `tab-menu` buttons according to their `index`.
```css
.tab-menu > button {
@ -23,72 +24,54 @@ Define `changeTab`, which will be executed when clicking a `<button>` from the `
```
```jsx
class Tab extends React.Component {
constructor(props) {
super(props);
this.state = {
bindIndex: props.defaultIndex
};
}
changeTab(newIndex) {
if (typeof this.props.onTabClick === "function")
this.props.onTabClick(newIndex);
this.setState({
bindIndex: newIndex
});
}
buttonClass(index) {
return this.state.bindIndex === index ? "focus" : "";
}
itemStyle(index) {
return {
display: this.state.bindIndex === index ? "block" : "none"
};
}
render() {
const items = this.props.children.filter(
item => item.type.name === "TabItem"
);
return (
<div className="wrapper">
<div className="tab-menu">
{items.map(({ props: { index, label } }) => (
<button
onClick={() => this.changeTab(index)}
className={this.buttonClass(index)}
>
{label}
</button>
))}
</div>
<div className="tab-view">
{items.map(({ props }) => (
<div
{...props}
className="tab-view_item"
key={props.index}
style={this.itemStyle(props.index)}
/>
))}
</div>
</div>
);
}
}
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>
);
}
```
```jsx
ReactDOM.render(
<Tab defaultIndex="1" onTabClick={console.log}>
<Tabs defaultIndex="1" onTabClick={console.log}>
<TabItem label="A" index="1">
Lorem ipsum
</TabItem>
<TabItem label="B" index="2">
Dolor sit amet
</TabItem>
</Tab>,
</Tabs>,
document.getElementById("root")
);