Code Steps

A Shopping Cart for Mars – Solution

December 01, 2019

This page shows the JavaScript and JSX for the “Shopping Cart for Mars” project.

It does not show the CSS.

import React from 'react';
import logo from './logo.svg';
import './App.css';
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
export default App;
import React from 'react';
import logo from './logo.svg';
import React from 'react';
import React from 'react';
human hamster ball, you can have fun inside and outside your
human hamster ball, you can have fun inside and outside your
human hamster ball, you can have fun inside and outside your
human hamster ball, you can have fun inside and outside your
human hamster ball, you can have fun inside and outside your
human hamster ball, you can have fun inside and outside your
human hamster ball, you can have fun inside and outside your
human hamster ball, you can have fun inside and outside your
human hamster ball, you can have fun inside and outside your
human hamster ball, you can have fun inside and outside your
human hamster ball, you can have fun inside and outside your
human hamster ball, you can have fun inside and outside your
human hamster ball, you can have fun inside and outside your
human hamster ball, you can have fun inside and outside your
human hamster ball, you can have fun inside and outside your
human hamster ball, you can have fun inside and outside your

We begin with the App.js file that npx create-react-app creates.

Remove the JSX that we won’t use.

(Sometimes I keep some code as an example until I’ve written mine, but I don’t see anything useful to me here.)

Removing this JSX causes React to warn that “logo” isn’t used. This is a distraction from useful warnings. Fix this by removing the import … from 'Logo' statement.

Add the code from the assignment instructions, for reference and to insure that we’re following the instructions.

Next, we’ll morph this into something that works for our shopping cart.

The instructions say “You must include enough information for viewers to understand what the product is and it’s [sic] price (so a product name, small description, price).”

Modify the objects in the array to include descriptions and prices.

(Thanks to Amy and Adib for products! I’ve abbreviated their descriptions; see their work for the full details.)

petsForAdoption is no longer an accurate name for this array. Rename it to a more descriptive variable name.

Add a single product, using just JSX.

This follows the development pattern: make something specific work first; then generalize it.

I might work on the JSX hierarchy and the CSS for a while, before getting back to JavaScript programming.

Note: create-react-app creates an app with uppercase CSS class names (“App”). CSS class names are generally lowercase (“product”). This code keeps create-react-apps’s capitalization for the CSS classes that come with it, but uses the lowercase convention for newly-introduced class names such as “product”.

“Factor out” the <div className="product">…</div> code to a component.

A React component is just a JavaScript function (1) with and uppercase name and (2) that return JSX.

This component returns exactly the JSX that was included directly inside App in the previous step.

(This checks off the requirement “You must have at least one other component besides your App() component.“)

Product always returns exactly the same JSX. This code will just display two “Oxygen bottle”s. It’s not (yet) reading the data from the products array.

Make the component read its data from the first product in the products array.

The component gets it data from its argument.

Now it’s easy to use the component a second time to render the second element of the array.

Add a props parameter to the Product component. The first time Product is called, props will equal { name: "Oxygen bottle" }, and props.name will therefore equal "Oxygen bottle". The second time Product is called, props will equal { name: "Fun Ball" }, and props.name will therefore equal "Fun ball". (These values come from the name property in <Product name="Oxygen bottle" /> and <Product name="Fun Ball" />.)

We could verify this by adding a line console.log("Product", props) before the return statement, and looking in the JavaScript console to see what is printed.

Now we can make use of this property. Instead of “hard-coding” the name in <div className="name">…</div> to the same string ("Oxygen bottle") each time, we’ll use the value of prop.name. This is a JavaScript value, so to use it inside of JSX, we need to put it inside curly braces { }.

Now, let’s read the description and price from props as well.

Note that we first parameterized only the name. Once this worked, we went back and parameterized the description and price. This way there was less to edit while testing the pattern for using a component property. Once we were sure this was working, we could copy the pattern for our other properties.

We’re still not using the data in the products array. Let’s fix that next.

Remember that a React component is just a JavaScript function. We’ve also seen that the JSX properties (name, description, and price) get bundled up in to a JavaScript object ({ name: …, description: …, price: … }).

The JSX code <Product name="Oxygen bottle" description="Indispensable for staying alive." price="100RMB" /> is the same as the JavaScript code Product({ name: "Oxygen bottle", description: "Indispensable for staying alive.", price: "100RMB" }).

(This isn’t normally the way you’d use this component. But it’s a useful stepping stone to map.)

This argument, { name: "Oxygen bottle", description: "Indispensable for staying alive.", price: "100RMB" }, happens to be the same as products[0]. Let’s use products[0] instead.

Now we’re finally making use of the data in the products array!

Go ahead and apply the same treatment to the second product.

(This checks off the requirements: “You must use an array of objects.” We’re finally using the data from the products array.)

These two lines:

  1. {Product(products[0])}
  2. {Product(products[1])}

create two values:

  1. The value returned by the function Product, when it is called with an argument that is the first value of the products array.
  2. The value returned by the function Product, when it is called with an argument that is the second value of the products array.

This is the same thing that map returns!

So we can replace these two lines by {products.map(Product)}.

(This checks off the requirement: “You must use the map() method at least once”.)

Unlike the repeated <Product … /> lines, {products.map(Product)} creates a Product component instance for each item in products. If we added a third item to products (thanks, Franklin!), a third item will automatically appear in the shopping cart.

Now we can add an image property to each of the products…

…and to the component.