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

@ -914,10 +914,11 @@ ReactDOM.render(<StarRating rating={2} />, document.getElementById('root'));
Renders a tabbed menu and view component. 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`. 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`. 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 ```css
.tab-menu > button { .tab-menu > button {
@ -936,39 +937,25 @@ Define `changeTab`, which will be executed when clicking a `<button>` from the `
``` ```
```jsx ```jsx
class Tab extends React.Component { function TabItem(props) {
constructor(props) { return <div {...props} />;
super(props); }
this.state = {
bindIndex: props.defaultIndex 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");
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 ( return (
<div className="wrapper"> <div className="wrapper">
<div className="tab-menu"> <div className="tab-menu">
{items.map(({ props: { index, label } }) => ( {items.map(({ props: { index, label } }) => (
<button <button
onClick={() => this.changeTab(index)} onClick={() => changeTab(index)}
className={this.buttonClass(index)} className={bindIndex === index ? "focus" : ""}
> >
{label} {label}
</button> </button>
@ -980,17 +967,13 @@ class Tab extends React.Component {
{...props} {...props}
className="tab-view_item" className="tab-view_item"
key={props.index} key={props.index}
style={this.itemStyle(props.index)} style={{ display: bindIndex === props.index ? "block" : "none" }}
/> />
))} ))}
</div> </div>
</div> </div>
); );
} }
}
function TabItem(props) {
return <div {...props} />;
}
``` ```
<details> <details>
@ -998,14 +981,14 @@ function TabItem(props) {
```jsx ```jsx
ReactDOM.render( ReactDOM.render(
<Tab defaultIndex="1" onTabClick={console.log}> <Tabs defaultIndex="1" onTabClick={console.log}>
<TabItem label="A" index="1"> <TabItem label="A" index="1">
Lorem ipsum Lorem ipsum
</TabItem> </TabItem>
<TabItem label="B" index="2"> <TabItem label="B" index="2">
Dolor sit amet Dolor sit amet
</TabItem> </TabItem>
</Tab>, </Tabs>,
document.getElementById("root") document.getElementById("root")
); );

View File

@ -215,11 +215,11 @@
{ {
"name": "Tabs.md", "name": "Tabs.md",
"title": "Tab", "title": "Tab",
"text": "Renders a tabbed menu and view component.\n\nDefine `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`.\nUse `Array.prototype.map` on the collected nodes to render the `tab-menu` and `tab-view`. \nDefine `changeTab`, which will be executed when clicking a `<button>` from the `tab-menu`.\n`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`.\n\n", "text": "Renders a tabbed menu and view component.\n\nDefine a `TabItem` component, pass it to the `Tab` and remove unnecessary nodes expect for `TabItem` by identifying the function's name in `props.children`.\nUse the `React.useState()` hook to initialize the value of the `bindIndex` state variable to `props.defaultIndex`. \nUse `Array.prototype.map` on the collected nodes to render the `tab-menu` and `tab-view`. \nDefine `changeTab`, which will be executed when clicking a `<button>` from the `tab-menu`.\n`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`.\n\n",
"codeBlocks": [ "codeBlocks": [
"```css\n.tab-menu > button {\n cursor: pointer;\n padding: 8px 16px;\n border: 0;\n border-bottom: 2px solid transparent;\n background: none;\n}\n.tab-menu > button.focus {\n border-bottom: 2px solid #007BEF;\n}\n.tab-menu > button:hover {\n border-bottom: 2px solid #007BEF;\n}\n```", "```css\n.tab-menu > button {\n cursor: pointer;\n padding: 8px 16px;\n border: 0;\n border-bottom: 2px solid transparent;\n background: none;\n}\n.tab-menu > button.focus {\n border-bottom: 2px solid #007BEF;\n}\n.tab-menu > button:hover {\n border-bottom: 2px solid #007BEF;\n}\n```",
"```jsx\nclass Tab extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n bindIndex: props.defaultIndex\n };\n }\n changeTab(newIndex) {\n if (typeof this.props.onTabClick === \"function\")\n this.props.onTabClick(newIndex);\n this.setState({\n bindIndex: newIndex\n });\n }\n buttonClass(index) {\n return this.state.bindIndex === index ? \"focus\" : \"\";\n }\n itemStyle(index) {\n return {\n display: this.state.bindIndex === index ? \"block\" : \"none\"\n };\n }\n render() {\n const items = this.props.children.filter(\n item => item.type.name === \"TabItem\"\n );\n return (\n <div className=\"wrapper\">\n <div className=\"tab-menu\">\n {items.map(({ props: { index, label } }) => (\n <button\n onClick={() => this.changeTab(index)}\n className={this.buttonClass(index)}\n >\n {label}\n </button>\n ))}\n </div>\n <div className=\"tab-view\">\n {items.map(({ props }) => (\n <div\n {...props}\n className=\"tab-view_item\"\n key={props.index}\n style={this.itemStyle(props.index)}\n />\n ))}\n </div>\n </div>\n );\n }\n}\nfunction TabItem(props) {\n return <div {...props} />;\n}\n```", "```jsx\nfunction TabItem(props) {\n return <div {...props} />;\n}\n\nfunction Tabs(props) {\n const [bindIndex, setBindIndex] = React.useState(props.defaultIndex);\n const changeTab = newIndex => {\n if (typeof props.onTabClick === \"function\") props.onTabClick(newIndex);\n setBindIndex(newIndex);\n };\n const items = props.children.filter(item => item.type.name === \"TabItem\");\n\n return (\n <div className=\"wrapper\">\n <div className=\"tab-menu\">\n {items.map(({ props: { index, label } }) => (\n <button\n onClick={() => changeTab(index)}\n className={bindIndex === index ? \"focus\" : \"\"}\n >\n {label}\n </button>\n ))}\n </div>\n <div className=\"tab-view\">\n {items.map(({ props }) => (\n <div\n {...props}\n className=\"tab-view_item\"\n key={props.index}\n style={{ display: bindIndex === props.index ? \"block\" : \"none\" }}\n />\n ))}\n </div>\n </div>\n );\n}\n```",
"```jsx\nReactDOM.render(\n <Tab defaultIndex=\"1\" onTabClick={console.log}>\n <TabItem label=\"A\" index=\"1\">\n Lorem ipsum\n </TabItem>\n <TabItem label=\"B\" index=\"2\">\n Dolor sit amet\n </TabItem>\n </Tab>,\n document.getElementById(\"root\")\n);\n\n```" "```jsx\nReactDOM.render(\n <Tabs defaultIndex=\"1\" onTabClick={console.log}>\n <TabItem label=\"A\" index=\"1\">\n Lorem ipsum\n </TabItem>\n <TabItem label=\"B\" index=\"2\">\n Dolor sit amet\n </TabItem>\n </Tabs>,\n document.getElementById(\"root\")\n);\n\n```"
], ],
"expertise": 1, "expertise": 1,
"tags": [ "tags": [

View File

@ -1,10 +1,11 @@
### Tab ### Tab
Renders a tabbed menu and view component. 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`. 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`. 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 ```css
.tab-menu > button { .tab-menu > button {
@ -23,39 +24,25 @@ Define `changeTab`, which will be executed when clicking a `<button>` from the `
``` ```
```jsx ```jsx
class Tab extends React.Component { function TabItem(props) {
constructor(props) { return <div {...props} />;
super(props); }
this.state = {
bindIndex: props.defaultIndex 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");
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 ( return (
<div className="wrapper"> <div className="wrapper">
<div className="tab-menu"> <div className="tab-menu">
{items.map(({ props: { index, label } }) => ( {items.map(({ props: { index, label } }) => (
<button <button
onClick={() => this.changeTab(index)} onClick={() => changeTab(index)}
className={this.buttonClass(index)} className={bindIndex === index ? "focus" : ""}
> >
{label} {label}
</button> </button>
@ -67,28 +54,24 @@ class Tab extends React.Component {
{...props} {...props}
className="tab-view_item" className="tab-view_item"
key={props.index} key={props.index}
style={this.itemStyle(props.index)} style={{ display: bindIndex === props.index ? "block" : "none" }}
/> />
))} ))}
</div> </div>
</div> </div>
); );
} }
}
function TabItem(props) {
return <div {...props} />;
}
``` ```
```jsx ```jsx
ReactDOM.render( ReactDOM.render(
<Tab defaultIndex="1" onTabClick={console.log}> <Tabs defaultIndex="1" onTabClick={console.log}>
<TabItem label="A" index="1"> <TabItem label="A" index="1">
Lorem ipsum Lorem ipsum
</TabItem> </TabItem>
<TabItem label="B" index="2"> <TabItem label="B" index="2">
Dolor sit amet Dolor sit amet
</TabItem> </TabItem>
</Tab>, </Tabs>,
document.getElementById("root") document.getElementById("root")
); );