Skip to content

Instantly share code, notes, and snippets.

@Hasstrup
Created September 2, 2020 19:28
Show Gist options
  • Save Hasstrup/24f5f08c76a63d63fd17226a24440dc5 to your computer and use it in GitHub Desktop.
Save Hasstrup/24f5f08c76a63d63fd17226a24440dc5 to your computer and use it in GitHub Desktop.
import React, { PureComponent } from "react";
// treating this as a parent component that has explicit knowledge of the presentation and behavior of it's
// children
class Dropdown extends PureComponent {
constructor(props) {
super(props);
this.state = {
isOpen: false,
};
}
// change toggle to arrow function to bind this correctly
toggle = () => this.setState({ isOpen: !this.state.isOpen });
render() {
const { isOpen } = this.state;
const { label, options, handleSelect } = this.props;
return (
<div className="dropdown">
<button
type="button"
className="dropdown-button"
id="dropdownButton"
aria-haspopup="true"
aria-expended={isOpen}
onClick={this.toggle}
>
{label}
</button>
<ul
className={`${isOpen ? "dropdown-open" : ""} dropdown-menu`}
aria-labelledby="dropdownButton"
role="menu"
>
{isOpen && options.map((option, index) => (
<DropdownItem
key={`${option}-${index}`}
value={option}
handleSelect={handleSelect}
/>
))}
</ul>
</div>
);
}
}
class DropdownItem extends PureComponent {
render() {
const { value, handleSelect } = this.props;
return (
<li>
<a onClick={(_) => handleSelect(value)}>{value}</a>
</li>
);
}
}
const pages1 = ["Page 1", "Page 2", "Page 3", "Page 4"];
const pages2 = ["Page 5", "Page 6"];
export class ExampleNav extends PureComponent {
constructor(props) {
super(props);
this.state = {
dropdown_1: false,
dropdown_2: false,
};
}
handleSelect = (dropdownKey, option) => {
this.setState({ [dropdownKey]: option });
// here we can choose to fetch
fetch("https://testapi.com/user", {
method: "PATCH",
body: JSON.stringify(this.state),
})
.then((res) => res.json())
.then((parsedResponse) => {}) // do something with the parsed response
.catch((err) => console.error(err)); // handle errors here using error boundary or a simple notification
};
render() {
return (
<nav>
<a href="/page1">Page 1</a>
<Dropdown
label="More items"
options={pages1}
handleSelect={(option) => this.handleSelect("dropdown_1", option)}
/>
<Dropdown
label="Even more items"
options={pages2}
handleSelect={(option) => this.handleSelect("dropdown_2", option)}
/>
</nav>
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment