Skip to content

Instantly share code, notes, and snippets.

@joel-daros
Created March 25, 2022 17:20
Show Gist options
  • Save joel-daros/eed7fe575dcb7c9ba39c17d936ea1d45 to your computer and use it in GitHub Desktop.
Save joel-daros/eed7fe575dcb7c9ba39c17d936ea1d45 to your computer and use it in GitHub Desktop.
Dropdown Joel Daros
/*
Prompt:
We have defined a basic dropdown via the Dropdown and DropdownItem components below, with example usage
in the ExampleNav component. The Dropdown and DropdownItem components have some problems, and also
have room for improvements (doesn't everything?) A couple items TODO here (make sure to explain with comments!)
0. How are you today? 😊
R: I'm great. :)
1. Please fix any obvious issues you see with the dropdown and then save your gist.
R: Fixed. the dropdown works.
2. Please then make improvements to the dropdown and then save your gist again.
R: I made a litle improvement to show the selected option.
3. Consider the different ways that this dropdown might be used and what changes would
be neccessary to make it more flexible.
R: Would be nice if you can:
* pass not only the text but also the value.
* You can navigate througth the avaliable options with the keyboard keys
* For large dropdown list items, you can do a realtime search for avaliable options.
* define style of the selected option
4. If we wanted to sync the dropdown selection to a server with this hypothetial "syncing library"
`app.sync('PATCH', 'users/'+app.USER.id, { dropdown_1_state: {true,false} })` where would this be included? Should
the state be read again from the server to show the dropdown open/closed on page load?
R: you need to load the data from the server in a useEffect hook for the first time the page loads, and work with the data loaded.
5. If we wanted to pass children (like this example) OR a Promise that resolves to an array of items
what changes should be made? (just a sentence or two or some code is ok).
R: Dropdown needs to receive an array of children items by params.
PS: No need to worry about CSS or about making it actually run.
*/
import React, { PureComponent } from 'react';
class Dropdown extends PureComponent {
// constuctor(props) { // fix constructor name
constructor(props) {
super(props);
this.state = {
isOpen: false,
selectedHref: '',
};
}
toggle = () => {
const { isOpen } = this.state;
// this.setState({isOpen: isOpen}); // isOpen can't receive the same value
this.setState({ isOpen: !isOpen });
};
onClickItem = (hrefSelected) => {
this.setState({ selectedHref: hrefSelected });
this.toggle();
};
render() {
const { isOpen, selectedHref } = this.state;
const { label, children } = this.props;
const childrenWithProps = React.Children.map(children, (child) => {
if (React.isValidElement(child)) {
return React.cloneElement(child, {
onClickItem: this.onClickItem,
selectedHref,
});
}
return child;
});
return (
<div className="dropdown">
<button
type="button"
className="dropdown-button"
id="dropdownButton"
aria-haspopup="true"
aria-expended={isOpen}
onClick={this.toggle}
>
{label}
</button>
{selectedHref ? <span>Selected Option: {selectedHref}</span> : ''}
<ul
className={`${isOpen ? 'dropdown-open' : ''} dropdown-menu`}
aria-labelledby="dropdownButton"
role="menu"
>
{/* first check if isOpen to show or not children itens */}
{isOpen && childrenWithProps}
</ul>
</div>
);
}
}
class DropdownItem extends PureComponent {
handleClick = () => {
const { href, onClickItem } = this.props;
// console.log(this.props);
onClickItem(href);
};
render() {
const { children } = this.props;
return <li onClick={this.handleClick}>{children}</li>;
}
}
class ExampleNav extends PureComponent {
render() {
return (
<nav>
<a href="/page1">Page 1</a>
<Dropdown label="More items">
<DropdownItem href="/page2">Page 2</DropdownItem>
<DropdownItem href="/page3">Page 3</DropdownItem>
<DropdownItem href="/page4">Page 4</DropdownItem>
</Dropdown>
<Dropdown label="Even more items">
<DropdownItem href="/page5">Page 5</DropdownItem>
<DropdownItem href="/page6">Page 6</DropdownItem>
</Dropdown>
</nav>
);
}
}
export default ExampleNav;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment