JSFiddle - React, Tailwind, and code Playground
[ASSIGNMENT] Close Frontend Application Quiz
by nathanlogan
HTML
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
CSS
h2 {
font-weight: bold;
padding: 1rem;
}
.Selected {
list-style: none;
padding: 0 0 0 1rem;
margin: 0 0 1rem;
}
.Selected__item {
display: inline-block;
margin-right: 0.5rem;
}
.Selected__item::after {
content: ', ';
}
.Selected__item:last-child::after {
content: '';
}
.List {
margin: 16px;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
grid-auto-rows: 60px;
grid-gap: 16px;
}
.List__item {
line-height: 60px;
text-align: center;
color: white;
text-shadow: 1px 1px rgba(0, 0, 0, 0.5);
box-shadow: 0px 1px 1px 0px rgba(0, 0, 0, 0.05);
}
.List__item:hover {
opacity: 0.7;
cursor: pointer;
}
.List__item-selected {
outline: 3px dashed red;
outline-offset: 1px;
}
/* Taken from https://clrs.cc/ */
.List__item--navy {
background-color: #001f3f;
}
.List__item--blue {
background-color: #0074d9;
}
.List__item--aqua {
background-color: #7fdbff;
}
.List__item--teal {
background-color: #39cccc;
}
.List__item--olive {
background-color: #3d9970;
}
.List__item--green {
background-color: #2ecc40;
}
.List__item--lime {
background-color: #01ff70;
}
.List__item--yellow {
background-color: #ffdc00;
}
.List__item--orange {
background-color: #ff851b;
}
.List__item--red {
background-color: #ff4136;
}
.List__item--maroon {
background-color: #85144b;
}
.List__item--fuchsia {
background-color: #f012be;
}
.List__item--purple {
background-color: #b10dc9;
}
.List__item--black {
background-color: #111111;
}
.List__item--gray {
background-color: #aaaaaa;
}
.List__item--silver {
background-color: #dddddd;
}
React
const { Fragment, useState } = React;
// Implement a feature to allow item selection with the following requirements:
// 1. Clicking an item selects/unselects it.
// 2. Multiple items can be selected at a time.
// 3. Make sure to AVOID UNNECESSARY RE-RENDERS (performance).
// 4. Currently selected items should be visually highlighted.
// 5. Currently selected items' names should be shown at the top of the page.
// Note:
// Below shows what I think you're shooting for in avoiding re-rendering. If the
// requirements are to avoid absolutely all possible re-renders, you could architect
// a solution that is based on each item maintaining its own internal state, and then
// it could trigger a parent function that would keep a copy of cumulative changes.
// It would then only rerender the "Currently selected" list (as its own component).
// The effect would be that some app context holds the state, and only the pieces
// that may change ever rerender. Practically, though, I think the below gets you there.
const List = ({ items }) => {
const [selected, setSelected] = useState([])
const toggleSelected = (name) => {
let newlySelected = []
if (selected.includes(name)) newlySelected = selected.filter(n => n !== name)
else newlySelected = [...selected, name]
setSelected(newlySelected)
}
return (
<Fragment>
<h2>Currently selected items ({selected.length})</h2>
<ul className="Selected">
{selected.map(name => (
<li key={name} className="Selected__item">{name}</li>
))}
</ul>
<h2>All items:</h2>
<ul className="List">
{items.map(item => (
<MemoizedItem
key={item.name}
color={item.color}
selected={selected.includes(item.name)}
onClick={() => toggleSelected(item.name)}
>
{item.name}
</MemoizedItem>
))}
</ul>
</Fragment>
)};
const Item = ({color, selected,...