Think about the last time that you ordered a pizza online. Mmmmm…
Part of the magical website that brought you tasty food was built with code like this:
import React, { useState } from "react"; const options = ["Bell Pepper", "Sausage", "Pepperoni", "Pineapple"]; export default function PersonalPizza() { const [selected, setSelected] = useState([]); const toggleTopping = ({target}) => { const clickedTopping = target.value; setSelected((prev) => { // check if clicked topping is already selected if (prev.includes(clickedTopping)) { // filter the clicked topping out of state return prev.filter(t => t !== clickedTopping); } else { // add the clicked topping to our state return [clickedTopping, ...prev]; } }); }; return ( <div> {options.map(option => ( <button value={option} onClick={toggleTopping} key={option}> {selected.includes(option) ? "Remove " : "Add "} {option} </button> ))} <p>Order a {selected.join(", ")} pizza</p> </div> ); }
JavaScript arrays are the best data model for managing and rendering JSX lists. In this example, we are using two arrays:
options
is an array that contains the names of all of the pizza toppings availableselected
is an array representing the selected toppings for our personal pizza
The options
array contains static data, meaning that it does not change. We like to define static data models outside of our function components since they don’t need to be recreated each time our component re-renders. In our JSX, we use the map
method to render a button for each of the toppings in our options
array.
The selected
array contains dynamic data, meaning that it changes, usually based on a user’s actions. We initialize selected
as an empty array. When a button is clicked, the toggleTopping
event handler is called. Notice how this event handler uses information from the event object to determine which topping was clicked.
When updating an array in state, we do not just add new data to the previous array. We replace the previous array with a brand new array. This means that any information that we want to save from the previous array needs to be explicitly copied over to our new array. That’s what this spread syntax does for us: ...prev
.
Notice how we use the includes()
, filter()
, and map()
methods of our arrays. If these are new to you, or you just want a refresher, take a minute to review these array methods. We don’t need to be full-fledged JavaScript gurus to build React UIs, but know that investing time to strengthen our JavaScript skills, will always help us do more faster (and have a lot more fun doing it) as React developers.
Instructions
Declare and initialize a state variable called cart
that will keep track of a list of string values.
Each of these string values represents a grocery item that we’ve added to our shopping cart. We’ll add event listeners and event handlers to add and remove items to our cart in the coming steps.
For now, let’s get started by initializing our cart
with the value of an empty array for the first render.
Add parameters to our two event handlers. addItem()
should accept an argument called item
and removeItem()
should accept an item called targetIndex
. Don’t worry about writing the function body for these event handlers just yet, we’ll do that in the next few steps!
Use array spread syntax to add a new item to our cart
state when the addItem()
function is called.
When the removeItem()
function is called, use the array filter()
method to remove the item from our state that’s located at the index of the item that was clicked in our list.
Why would we want to use the index of the clicked item instead of the item itself when determining what to remove from our data model? Say that we have two of the same item in an array. Using the value to remove the item would remove all items with that value, so we use the index as a unique identifier.