• React
  • CSS
  • JavaScript

Implement a Simple List Selection Component With React

July 14, 2020 • 2 min read

Useful for navigation menus and routing indication.

Previously I had worked on a list component that needed to change the style of a list item once a user clicks on it. In this post I will show how a component like that can be easily implemented with React. The implementation discussed here can also be applied to navigation menus, or any other component where the user is selecting from a list of choices.


In this example we will implement a breakfast list where the user can select their favorite breakfast, and display it at the top to them. List Selection Component Preview

1. Build the Static Version

First, let's build a static version of the component. This means no state or stateful logic will be added. Here's what that looks like.


1
// App.js
2
3
import React from 'react'
4
5
export default function App() {
6
return (
7
<div className="App">
8
<h1>List Selection Example</h1>
9
<ul className="breakfastList">
10
<li>Pancakes</li>
11
<li>Cereal</li>
12
<li>Eggs</li>
13
</ul>
14
</div>
15
)
16
}

2. Adding State

From the photo above we see that we will display a sentence that says what the user likes for breakfast, and we keep track of what breakfast option was selected. This means we should have state for the users favorite breakfast and state to keep track of what breakfast option has been selected. To keep things simple, we will only allow three breakfast options, pancakes, cereal, and eggs.


1
// App.js
2
3
import React, { useState } from "react";
4
5
export default function App() {
6
const [favoriteBreakfast, setFavoriteBreakfast] = useState(null);
7
const [breakfastOptions, selectBreakfast] = useState({
8
pancakes: false,
9
cereal: false,
10
eggs: false
11
});
12
...
13
}

All breakfast options are false by default indicating that no breakfast option has been selected.

3. Update Rendering Logic

Now we can utilize the state variables to add to our rendering logic. First we will update the original JSX rendered by the App component to have proper classnames, and use the selected breakfast option to apply the right styles to list item that is clicked.

Update JSX

1
// App.js
2
...
3
4
return (
5
<div className="App">
6
<h1>List Selection Example</h1>
7
<p>
8
{favoriteBreakfast
9
? `I love ${favoriteBreakfast} for breakfast!`
10
: "Select your favorite breakfast!"}
11
</p>
12
<ul className="breakfastList">
13
<li
14
className={
15
breakfastOptions.pancakes
16
? "breakfastList-listItem breakfastList-listItem--selected"
17
: "breakfastList-listItem"
18
}
19
>
20
Pancakes
21
</li>
22
<li
23
className={
24
breakfastOptions.cereal
25
? "breakfastList-listItem breakfastList-listItem--selected"
26
: "breakfastList-listItem"
27
}
28
>
29
Cereal
30
</li>
31
<li
32
className={
33
breakfastOptions.eggs
34
? "breakfastList-listItem breakfastList-listItem--selected"
35
: "breakfastList-listItem"
36
}
37
>
38
Eggs
39
</li>
40
</ul>
41
</div>
42
);

Quick Breakdown

Just want to go a little deeper into the following rendering logic.


1
<li
2
className={
3
breakfastOptions.pancakes
4
? "breakfastList-listItem breakfastList-listItem--selected"
5
: "breakfastList-listItem"
6
}
7
>

This is saying that if breakfastOptions.pancakes is true the classname for this list item will be "breakfastList-listItem breakfastList-listItem--selected". Otherwise, the classname will be just "breakfastList-listItem". We provide two classnames when a list item is selected, one for the default look of the list item, and one for the selected version.


Add CSS Styles

Now we will create the styles sheet to apply css styles to our component.


1
// styles.css
2
3
.App {
4
font-family: sans-serif;
5
text-align: center;
6
}
7
8
.breakfastList {
9
padding: 20px;
10
border-radius: 5px;
11
max-width: 400px;
12
margin: 25px auto;
13
}
14
15
.breakfastList-listItem {
16
list-style-type: none;
17
margin: 15px;
18
padding: 10px;
19
background-color: rgb(188, 3, 245);
20
color: whitesmoke;
21
letter-spacing: 0.8px;
22
cursor: pointer;
23
}
24
25
.breakfastList-listItem:hover {
26
border: none;
27
border-bottom: 3px solid rgb(85, 85, 3);
28
}
29
30
.breakfastList-listItem--selected {
31
background-color: black;
32
border: 2px solid yellow;
33
}

Now that we have our styles, we can import it into our App component.


1
...
2
import "./styles.css";
3
...

This is possible with a bundler like Webpack. This code is hosted on codesandbox, which handles the bundling for us.


At this point your app should look very similar to the example photo above but without the selection styles applied to any list item.

4. Add Selection Logic

Let's add the logic for selecting a choice from the list. Since all the breakfast choices are initially false, when a user clicks on a list item, we need to set it's corresponding breakfast choice to true and update all other choices to be false. Here's what that logic looks like.


1
const invertObjectSelection = (keySelected, objectToInvert) => {
2
if (objectToInvert[keySelected]) {
3
return objectToInvert
4
}
5
6
objectToInvert[keySelected] = true
7
8
for (let key in objectToInvert) {
9
if (key !== keySelected) {
10
objectToInvert[key] = false
11
}
12
}
13
14
return objectToInvert
15
}

This function will be used in the onClick handler we will provide to each list item. This handler will be provided an event object that it uses to get the value of the breakfast choice. It sets the favorite breakfast, and then calls invertObjectSelection which will update out state for breakfast choices, and therefore update the look of our breakfast menu.


1
function handleClick(event) {
2
const selectedBreakfast = event.target.innerHTML
3
setFavoriteBreakfast(selectedBreakfast)
4
selectBreakfast(
5
invertObjectSelection(selectedBreakfast.toLowerCase(), breakfastOptions)
6
)
7
}

Now, to call the handleClick above when the user clicks on a breakfast choice, update each list item to have the handleClick function provided to onClick. It should look like this:


1
<li
2
onClick={handleClick}
3
className={
4
breakfastOptions.pancakes
5
? 'breakfastList-listItem breakfastList-listItem--selected'
6
: 'breakfastList-listItem'
7
}
8
>
9
Pancakes
10
</li>

When the user clicks on the Pancakes option or any other option in the list, the handleClick will run and update the state, therefore updating our UI since we reference state values in the render() function.

Take Away

For this tutorial, I hope you learned how to use stateful logic and boolean values to style and control rendering of your UI. Specifically, I hope it was useful to show you how to build a simple list that can provide users feedback on what they have selected.


To make this more interesting, consider:

  • Extending the implementation for any number of items in the list.
  • Update the CSS styles to something different than what we have now.

Let me know what you come up with!