Created
June 25, 2021 17:39
-
-
Save ejmudi/857dbc16a9bde452fd1f607c92175f40 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| 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