Skip to content

Instantly share code, notes, and snippets.

@bnorton
Last active February 23, 2023 12:50
Show Gist options
  • Save bnorton/7bccc6787ffbf67dfe05f75798daf3da to your computer and use it in GitHub Desktop.
Save bnorton/7bccc6787ffbf67dfe05f75798daf3da to your computer and use it in GitHub Desktop.
Chameleon React.js Developer - Technical exercise
/*
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 and then save your gist.
2. Please then make improvements to the dropdown and then save your gist again.
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 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?
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 or about making it actually run.
*/
import React, {PureComponent} from 'react';
class Dropdown extends PureComponent {
constuctor(props) {
super(props);
this.state = {
isOpen: false,
};
}
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-expended={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() {
// TODO implement me
}
}
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>
);
}
}
@EmmanuelTheCoder
Copy link

Hi there, I think you should refractor your technical test to functional components. I really hope your React codebase is not in class based component because that would be like doing legacy coding.

@bnorton
Copy link
Author

bnorton commented Feb 16, 2022

thanks for the feedback @EmmanuelTheCoder! I find that part of the challenge of working with new and ever-changing technologies is the likelihood that some of your codebase is out of date with current best practices. Success would be to have the type of traction with your product that you get the opportunity to refactor and build on the latest and greatest. 👍

@EmmanuelTheCoder
Copy link

True. Wish you the best with that.

@Wahidul505
Copy link

import React, { PureComponent } from 'react';

class Dropdown extends PureComponent {
// Bug: wrong name
constructor(props) {
super(props);
this.state = {
isOpen: false,
selectedItem: '',
};
}

// Bug: bind or change to arrow function
toggle = () => {
const { isOpen } = this.state;
// Bug: wrong state update
this.setState({ isOpen: !isOpen });
};

onClickItem = val => {
const { selectedItem } = this.state;
const { onChange } = this.props;
if (val !== selectedItem) {
this.setState({ selectedItem: val });
this.toggle();
if (onChange) {
onChange(val);
}
}
};

render() {
const { isOpen, selectedItem } = this.state;
const { label } = this.props;
console.log('selectedItem', selectedItem);
const childrenWithProps = React.Children.map(this.props.children, child => {
return React.isValidElement(child)
? React.cloneElement(child, { onClickItem: this.onClickItem, selectedItem })
: child;
});
return (



{label}

    <ul
      className={`${isOpen ? 'dropdown-open' : ''} dropdown-menu`}
      aria-labelledby="dropdownButton"
      role="menu"
    >
      {/* Bug: Add condition */}
      {isOpen && childrenWithProps}
    </ul>
  </div>
);

}
}

class DropdownItem extends PureComponent {
handleClick = () => {
const { href, onClickItem } = this.props;
onClickItem(href);
};

render() {
const { children, selectedItem, href } = this.props;
const isSelected = selectedItem === href;
return (
<li style={{ color: isSelected ? 'red' : '' }} onClick={this.handleClick}>
{children}

);
}
}

export default class ExampleNav extends PureComponent {
render() {
return (


Page 1

Page 2
Page 3
Page 4


Page 5
Page 6


);
}
}

@AYOMITIDE-OAJ
Copy link

import React, {PureComponent} from 'react';

class Dropdown extends PureComponent {
/* miss spelling of the keyword constructor */
constructor(props){
super(props);
this.state = {
isOpen: false,
selectedItem: " ",
};
}
// arrow function correction
toggle = () => {
const { isOpen } = this.state;
// Bug: wrong state update
this.setState({ isOpen: !isOpen });
};

onClickItem = val => {
const { selectedItem } = this.state;
const { onChange } = this.props;
if (val !== selectedItem ){
this.setState({
selectedItem: val
});
this.toggle();
if(onChange){
onChange(val);
}
}
};

render(){
const { isOpen, selectedItem } = this.state;
const { label } = this.props;
const childrenWithProps = React.Children.map(this.props.children, child => {
return React.isValidElement(child)
? React.cloneElement(child, { onClickItem: this.onClickItem, selectedItem})
: child
});
return(


<ul className={${isOpen ? 'dropdown-open' : ''}dropdown-menu}
aria-labelledby="dropdownButton"
role="menu">
{/* Bug: Add a Double Condition Check */}
{isOpen && childrenWithProps}


);
};

class DropdownItem extends PureComponent {
handleClick = () => {
const { href, onClickItem } = this.props;
onClickItem(href);
};

render(){
  const { children, selectedItem, href} = this.props;
  const isSelected = selectedItem === href;
  return (
    <li style={{ color: isSelected ? 'red':''}} onClick={this.handleClick}>
      {children}
    </li>
  );
}

}

export default class ExampleNav extends PureComponent {

}
}

@al-waheed
Copy link

class Dropdown extends PureComponent {
//mispelling of contructor
constuctor(props) {
super(props);
this.state = {
isOpen: false,
};
}

toggle() {
const {isOpen} = this.state;
//Error in state update instead of " this.setState({isOpen: !isOpen}"
this.setState({isOpen: isOpen});
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment