Skip to content

Instantly share code, notes, and snippets.

@ejmudi
Created June 25, 2021 17:39
Show Gist options
  • Select an option

  • Save ejmudi/857dbc16a9bde452fd1f607c92175f40 to your computer and use it in GitHub Desktop.

Select an option

Save ejmudi/857dbc16a9bde452fd1f607c92175f40 to your computer and use it in GitHub Desktop.
/*
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? 😊
1. Please fix any obvious issues you see with the dropdown.
2. Please then make improvements to the dropdown.
3. Consider the different ways that this dropdown might be used and what changes would
be neccessary to make it more flexible.
4. If we wanted to sync this dropdown selection to the server with
app.sync('PATCH', 'user', { dropdown_1_state: {true,false} }) where would this be included?
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).
PS: No need to worry about CSS.
*/
/*
------------------------------------------------
ANSWERS!!:
2a - I fixed the toggle to toggle the `dropdown-open` class appropriately by binding the handler and modifying the function
to set to it's opposite value in state.
2b - I also Refactored the Dropdown and DropdownItems to data i.e this.dropdowns instead of Hardcoding what could turn out to
be a long list of dropdowns later on.
3. The ExampleNav component could have the dropdown values sent in as a prop.
4. We would need to create a Service Layer to handle http requests, create a function in it that accepts the values
to be sent to the server as an argument and then import it and use here in the component on dropdown Select (click in this case of our code) event.
5. I created a new parent component(PromisePropExample) to demonstrate passing a promise as a prop to the ExampleNav component using the PromisePropExample component below.
We pass a Promise Prop named `promise` to the ExampleNav component, and it is resolved in the ComponentDidUpdate of ExampleNav, It's value set in state and component rerendered.
*/
import React, { PureComponent } from 'react';
class Dropdown extends PureComponent {
constructor(props) {
super(props);
this.state = {
isOpen: false
};
this.toggle = this.toggle.bind(this);
}
toggle() {
const { isOpen } = this.state;
this.setState({ isOpen: !isOpen });
}
render() {
const { isOpen } = this.state;
const { label } = this.props;
return (
<div className="dropdown">
<button type="button" className="dropdown-button" id="dropdownButton" aria-haspopup="true" aria-expanded={isOpen} onClick={this.toggle}>{label}</button>
<ul className={`${isOpen ? 'dropdown-open' : ''} dropdown-menu`} aria-labelledby="dropdownButton" role="menu">
{this.props.children}
</ul>
</div>
);
}
}
class DropdownItem extends PureComponent {
render() {
return (
<li>
<a href={this.props.href}>{this.props.children}</a>
</li>
);
}
}
class ExampleNav extends PureComponent {
constructor(props) {
super(props);
this.state = {
promisedValue: "This will be replaced with a Resolved Promise Value"
}
}
componentDidUpdate() {
if (this.props.promise) {
this.props.promise.then((promisedValue) => {
this.setState({
promisedValue
});
});
}
}
dropdowns = [
{
label: "More items",
items: [
{
href: "/page2",
value: "Page 2"
},
{
href: "/page3",
value: "Page 3"
},
{
href: "/page4",
value: "Page 4"
}
]
},
{
label: "Even More items",
items: [
{
href: "/page5",
value: "Page 5"
},
{
href: "/page6",
value: "Page 6"
}
]
},
];
render() {
return (
<nav>
<a href="/page1">Page 1</a>
{this.dropdowns.map(({ label, items }, i) => (
<Dropdown key={i} label={label}>
{items.map(({ href, value }, j) => (
<DropdownItem key={j} href={href}>{value}</DropdownItem>
))}
</Dropdown>
))}
<h2><strong>{this.state.promisedValue}</strong></h2>
</nav>
);
}
}
class PromisePropExample extends PureComponent {
constructor() {
super();
this.timeout = null;
this.state = {
promise: new Promise(() => null)
}
}
componentDidMount() {
const promise = new Promise((resolve) => {
this.timeout = setTimeout(() => resolve("Resolved Promise Value: Mudiaga Ejenavi"), 3000);
});
this.setState({
promise
});
}
componentWillUnmount() {
clearTimeout(this.timeout);
}
render() {
return (
<ExampleNav promise={this.state.promise} />
);
}
}
export default PromisePropExample;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment