News

Travis CI set up notes -- how to set up the Travis Continuous Integration server for building React apps and deploying to Firebase
Quick, React! -- my first draft at a modern React tutorial. Ready for review. Post questions, bugs, requests, on Piazza.
Learn React Task -- a personal activity to help everyone learn (or practice) building React apps the modern way
React: Old vs New -- a demonstration of how functional React is simpler to code than old React.
First Demo Task -- due Tuesday
Team React Setup Task and Four-Panel Storyboard Task -- What each team needs to have done before the second class!
Day One Task -- What each team needs to be ready to present on the first class!

When

TTh 11am - 12:20am

Where

Tech A110

Who

Chris Riesbeck

Resources

Learning Modern React Design

There's a lot to learn with React, but some basic ideas can make building apps simpler, with code that is cleaner and easier to understand and debug. Those ideas are:

More on this below.

Even if you know React, do this activity. Very few students have yet learned how to use React with Hooks well. If you're not sure, take a look at this first code sample.

Prerequisites

Brush Up on Modern JavaScript

You should be familiar with modern JavaScript coding. Much has changed in the past few years. A good reference is Modern JavaScript. A good one-page resource for React is the React Handbook.

Install your Tools

Install NodeJS. If you already have, be sure it's up to date. You need npx from the new versions of Node to run the create-react-app script.

Install the React Devtools for your browser. create-react-app does a lot of repackaging of your source HTML and JavaScript for deployment. The HTML and JavaScript the browser gets is very different from what you wrote. The devtools read metadata generated by create-react-app so that you can interact with your original source in the browser debuggers.

Do the Quick, React! Tutorial

Do the Quick, React! tutorial. This introduces the essential JavaScript and React programming concepts needed to get a React app going on a clean solid basis. It includes functional components, stylng, fetching data, interactive UI state handling, working with the Firebase real-time database, and authentication with Firebase.

It follows the Agile approach of implementing applications in very thin end-to-end vertical slices, using the React development process described in the Thinking in React tutorial:

A slice is a thin bit of your app, including user interface and back end. Do not do all front-end first, or all back-end first. What you choose to do in each slice is largely up to you, but it should something that either provides the most value for the end user or reduces the most risk on the technical side.

The App

This activity challenges you to build a moderately complicated shopping cart app.

If you are doing this in one of my courses, I will provide spreadsheet for reporting progress, via Canvas. This is where you will enter links to your repo, your app's public site, and the various commits along the way that commplete each subtask.

Your goal is to build an app very similar to this shopping cart app.

Play with this app briefly to see how it works. Some parts of it are obvious. Some parts are not, e.g., how to remove an item from the cart, and what text like "9 x $1.21" means.

Backlog

Here is the prioritized backlog of user stories for your app, broken down into user-testable releases.

Release 1: Catalog page

Release 2: Basic shopping

Release 3: Persistence and Inventory

Create your app repository

Use create-react-app to create an empty shell for your shopping cart app.

npx create-react-app new-shopping-cart

Test that your empty app runs.

cd new-shopping-cart
npm start

The React web page should open in your browser.

Stop the server.

Create a repo for your app on github. Commit your code to it.

Put your name and a clickable link to the Github repo in the Learn React Report spreadsheet (link on Canvas).

Commit often to your local repo. Commit to github when something new works, but never break master.

Go public

Even though you don't have anything real yet, set up a public host for your project, so that you can user test and show your client, e.g., me., where you're at.

There are many web hosting services for dynamic web apps running NodeJS, such as Firebase, Heroku, and AWS. We’ll give instructions for Firebase. It provides three services for free that we need here: hosting, authentication, and a database.

Create an account at Firebase, if you don’t already have one.

Create a Firebase project at Firebase. This will be the back-end for your app. You can call it anything, but choose something the same as or close to your app name.

Add a database to the Firebase project. Be sure to choose the real-time database, not Firestore. Create it in test mode, to avoid permission issues.

In a terminal window on your machine, install the Firebase CLI globally with

npm install -g firebase-tools

Switch into your local app directory and initialize your app's Firebase configuration:

firebase init

Choose both hosting and the real-time database.

More on setting up Firebase apps.

When initialization finishes, build and deploy

npm run build
firebase deploy

This will assemble your app and deploy it to Firebase.

If deployment fails, it's probably because you are not logged into Firebase. Do firebase login and try to deploy again.

Open the URL for your app generated by Firebase. Verify that the app is working, images and all.

Create and commit your working app to github. Put your public URL on the report spreadsheet.

From this point on, your process for closing each task will be

Implement a static page

Always start an app by building the static view. This will give you something you can test and show to users, and provide the basis for designing the interactive parts. There are several steps to creating a static catalog page.

Design and test your data

Always use realistic data. No dummy "lorem ipsum" stuff. Keep the amount of data small but complete enough to demonstrate the user stories you want to implement first.

Organize your data into a logical JSON structure.

For this project, use this products.json file. It's a modified version of the one in Ribeiro's shopping cart.

Put this JSON file somewhere under the application's public directory. This will make it easy to fetch at runtime. We'll assume here the file is in public/data/products.json.

Now replace the entire contents of the default src/App.js file with

import React, { useEffect, useState } from 'react';

const App = () => {
  const [products, setProducts] = useState([]);
  useEffect(() => {
    const fetchProducts = async () => {
      const response = await fetch('./data/products.json');
      const json = await response.json();
      setProducts(Object.values(json));
    };
    fetchProducts();
  }, []);

  return (
    <ul>
      {products.map(product => <li key={product.sku}>{product.title}</li>)}
    </ul>
  );
};

export default App;

If you don't know what the above code does, re-read Quick,React!

Run your app. If everything is set up correctly, instead of the React logo, you should see a plain list of the product titles. When this works, you're ready to do a real display of that data.

When your app is working locally and on the public site, commit to github, and update the progress sheet. Don't forget to npm run build before doing firebase deploy.

Design your UI component hierarchy

Create a sketch of the UI similar to that in the example app, using pencil and paper, a sketching tool, or an annotated screen grab of the current UI.

Study the example on Thinking in React:

On your UI sketch, outline what you think would be appropriate containers and components.

Implement the components

Here, your app needs to show the T-shirt pictures, names, and prices, and the buttons for selecting a size. Even this is a lot to build, if you don't know React. The way to get things done is to follow the agile Thinking in React process and work in tiny functional slices. The following would be good slices. They can be done in almost any order:

Steal code ideas from React Old and New and the example app repository, but be aware that the shopping cart code includes an Express server, Redux state management (not needed for something this simple), a fairly complex component hierarchy, and bare CSS rather than a React style package.

As soon as a slice works, test it on your public host. When the entire page displays correctly, commit to github, and update the report spreadsheet.

Put the images from the example app repository under the public folder, e.g., public/data/products/.

Style your app with a React-compatible framework, such as

This chart shows the number of downloads from Github for each package.

When your app is working locally and on the public site, commit to github, and update the progress sheet.

Add interaction

Adding the ability to add items to a cart means adding what React calls state. Read carefully what Thinking in React says counts as state. State has to do with the local user interface, not the state of the application. State in React does not include static data, nor anything that can be calculated from other bits of state.

The trick to implementing state is to first create the state variables with different values, and update your static display code to show the state appropriately. Don't try to implement state change until static state display works.

Identify the necessary state

In this case, there are two pieces of UI state:

Implement static state diplay

Add state using the useState() hook. Define the new state in the smallest containing component possible.

This makes the app easier to maintain and modify, and reduces how much prop passing you have to do.

Do states in tiny slices, e.g., first do the state variable for whether the cart is open or closed. Test by initializing the variable to true and false, and make sure the shopping is visible only when it's supposed to be. After that works, add the state variable for the list of items selected so far. Be sure to be able to handle more than one of an item. Initialize with different lists and verify that the cart shows the right list, and, eventually, the right total cost.

More on state.

When your app is working locally and on the public site, commit to github, and update the progress sheet.

Implement interactive state

This is where you add interactivity to your app. There are three primary user actions: viewing the cart, adding items to the cart, and removing items from the cart. That's a good order to do them in.

Do opening and closing the cart first. Clicking on the cart icon or any "buy" button should open the cart. Click on the close button should close the cart.

See React Old and New for how to do this.

When your app is working locally and on the public site, commit to github, and update the progress sheet.

Now implement adding items to the cart. Adding an item should automatically open the cart and update the total.

When your app is working locally and on the public site, commit to github, and update the progress sheet.

Add removing items from the cart.

Add a control for removing an item. If more than one of a specific item has been selected, the count should be decremented by one.

When your app is working locally and on the public site, commit to github, and update the progress sheet.

Fetch from a database

Up to this point, all the data has been static. Most interesting web applications need to keep dynamic data on a server, whether it be game scores, comment posts, or whatever.

For this project, two examples of dynamic data would be

Start with the inventory, since it doesn't require implementing authentication.

Show availability in your user interface

Use useState() to add a state variable for inventory, with an initial small inventory of just a few shirt sizes.

Copy some of the data from inventory.json.

Update your product display code to only show size buttons for available sizes of each shirt. If no sizes are available, show a non-clickable "out of stock" text message.

Update your code to take into account the items in the shopping cart. Verify that when you select the last available size of a shirt, that size becomes out of stock. If you remove that size shirt from the cart, it becomes available agint.

When your app is working locally and on the public site, commit to github, and update the progress sheet.

Add a database

The Firebase Real-time Database (Firebase RT) is a very simple cloud database. Everything is stored as one big JSON object. Every subitem should be indexed under a stable unchanging sequences of keys. Both products.json and inventory.json are Firebase-compatible.

Initialize the inventory

Initialize the database with inventory.json file, using the Firebase console import command.

Importing a JSON file completely replaces all data. Only do this to initialize or reset your database.

Fetch inventory from the database

Add code to get the inventory data from Firebase and store it in your local inventory state variable.

See this section of the Quick, React! tutorial.

Verify that all shirt sizes not listed in the inventory file no longer appear on the catalog page. Verify that adding and removing items from the cart still updates the available sizes appropriately.

When your app is working locally and on the public site, commit to github, and update the progress sheet.

Add authentication

Many developers do user accounts and login first. That's a terrible idea. There is nothing to be learned about your app idea from implementing login.

But once you have a working prototype that suggests your app is a good idea, you will probably want to keep track of users. Shopping is clearly an application that needs to know who someone is when they checkout.

Add user identity to your app

Add the ability to sign up and log in.

Firebase supports multiple authentication options, e.g., email, Facebook, and Google. Add at least one form of authentication to your app. Google and email are quite simple, thanks to Firebase.

If the user is not logged in, your interface should show buttons to log in or sign up. If the user is logged in, your interface should show who is logged in and a logout button.

More on authentication with Firebase.

When your app is working locally and on the public site, commit to github, and update the progress sheet.

Add database updating

Add persistent shopping carts

Change your app so that the shopping cart for a logged-in user is automatically saved under the carts/userid key in the database, whenever the cart changes.

Verify that you see the data appear on the Firebase console.

Add code so that when a user logs in, any saved items are added to the current shopping cart. Don't replace the current cart. The user may have selected some items before logging in. The user can always delete old items if they want to.

Careful! The logic for this has many edge cases. For example, whatever the user has selected plus the old cart may not be valid, given the currently available stock. When that happens, the cart has to be adjusted and a message appear telling the user what happened. This message should display until the user closes it.

When your app is working locally and on the public site, commit to github, and update the progress sheet.

Add stock updating

Change your app so that when a user checks out, any items in their cart are removed from the inventory on the database.

This may cause other carts to contain items no longer available. Verify that pages of other users properly update and alerts those users if any items in the cart had to be removed. Test by logging in as two different users, on two different browsers. Set up the shopping carts such that hen one user checks out, the other user's cart has to be adjusted.

When your app is working locally and on the public site, commit to github, and update the progress sheet.