# Welcome to Bootcamp!

## Overview

Welcome! [Coding Bootcamp](https://www.rocketacademy.co/courses/bootcamp-course) is Rocket Academy's flagship career-conversion course. It builds on concepts from Rocket's intro coding course [Coding Fundamentals](https://www.rocketacademy.co/courses/coding-fundamentals). On completion of Coding Bootcamp, students can expect to get jobs as software engineers.

## Learning Objectives

What makes a good software engineer? Rocket aims to teach both hard and soft skills one needs to succeed.

1. Hard skills (base competency)
   1. General software knowledge
      1. App architecture
      2. How the internet works
      3. Database design
   2. Foundational technologies
      1. HTML, CSS, JS, React, Firebase, Express, SQL, Sequelize, Algorithms
2. Soft skills (extremely underrated and highly valued)
   1. Teamwork
      1. Ask technical questions
      2. Write technical documentation
      3. Perform code reviews
      4. Communicate technical tradeoffs
   2. Code quality
      1. Naming, commenting, decomposition
      2. Git best practices

## Curriculum Outline

Rocket's Bootcamp contains 4 modules of 16 course days each, each of which culminates in a project. Rocket requires students complete module projects to continue in Coding Bootcamp.

1. Frontend
   1. Build UI with HTML, React and CSS (individual project)
2. Full Stack
   1. Build full-stack app with Firebase backend (group project)
3. Backend
   1. Build full-stack app with Express backend (individual or group project)
4. Capstone
   1. Build app with new technology (individual or group project)

The following is a diagram of Rocket's curriculum. Module 1 introduces the relationship between client and server and how a frontend server can serve a client-side application. Module 2 introduces a 3rd-party backend service (Firebase) that our frontend apps can use to store data. Module 3 introduces how to build a backend service of our own. Throughout the course we will learn algorithms to bolster our foundations and prepare for coding interviews.

![Coding Bootcamp Curriculum Outline](/files/8VwL2r4R6GqdllkDAdV8)

You may notice Rocket's docs often reference official docs, guides and tutorials for the content we teach, for example with React, Firebase and Sequelize. We do this because the official docs are often the best explanations, and Rocket supplements those explanations with our own expertise of what students at our levels are likely to understand. All Rocket exercises are intentionally and meticulously designed to suit our students' experience levels.

We hope this teaching style suits you and we are excited to teach you the best!


# Logistics


# Course Schedules

## Batch-Specific Schedules

Rocket Academy runs several Coding Bootcamp batches concurrently.

Please check your latest schedules on the LMS:

<https://skills.disco.co>


# Course Methodology

## Flipped Classroom

Rocket adopts a flipped-classroom model where Rocket expects students to review lectures and course materials before class, and spend class time clarifying concepts and completing exercises with the guidance of a section leader.

## How to unblock yourself

### General tips

Rocket recommends the following 3 steps to unblock ourselves when blocked on a problem.

1. Trace the error message. What could be causing this error message? If we address that and there is another error message, keep addressing until there are no more error messages. If you do not see an error message, find where it is and/or find a way to give yourself more clues, e.g. with `console.log` statements.
2. Google the error message and context, e.g. "PropTypes not defined React". Skim through Google results and dig deeper in results that seem more promising.
3. Ask your peers and section leader in your section Slack channel, sharing context about the problem and what you've learnt from Steps 1 and 2 above. Context will allow them to help you. Rocket mostly uses mainstream technologies and our problems will not be overly difficult.

### How to use Google

Students will need to use Google as a resource to solve problems not explained in Rocket's curriculum. Rocket will do our best to document the most common mistakes, but it would be impossible to document all. Professional SWEs spend most time finding answers on Google, and googling effectively may be your most important takeaway from Bootcamp.

When searching on Google, generally search for a combination of your error message and relevant technology name. For example, "Uncaught TypeError: Cannot read properties of null JavaScript" (JavaScript is the technology in this example). This will allow Google to share results for the specific error we are seeing for the specific technology.

With experience you will know when you are on the right track. Often it takes multiple permutations of Google search keywords to find the answer we are looking for. The goal when reading documentation, Stack Overflow or forum answers is to find relevant information as quickly as possible without reading more than necessary.

### How to ask questions to get help

Always provide context with questions. Helpful context for technical questions can include:

1. What is the error message?
2. What do you think is the problem?
3. What have you learnt from debugging and googling?
4. What is the relevant code causing the problem?

Compare the following 3 questions. Notice how it becomes much easier to help someone the more context we have about their problem.

#### Question 1: No context

> "My code is not working. Please help!"

#### Question 2: Incomplete context

> "My code is not working. I'm getting the error "Uncaught TypeError: Cannot read properties of null (reading 'rank')". Please help!"

#### Question 3: Full context

> "I'm getting the error 'Uncaught TypeError: Cannot read properties of null (reading 'rank')' on line 3. On line 3 I'm accessing a property of object `card` from my card deck. Googling tells me that `card` must be `null`, but I am not sure why. I've attached the relevant code below. Any suggestions?"
>
> ```javascript
> const cardDeck = [null];
> const card = cardDeck[0];
> console.log(card.rank);
> ```

### **How to document your errors**

In this section, we will be looking at how we can document errors, this will facilitate your debugging process and make asking for help much easier.

### Frontend React Error

When handling errors in a React frontend, you can usually see an error message in the Command Line Interface where you executed the command ‘npm start’, as well as the console of the browser. The browser usually emulates the error that is found in the Command Line Interface, so the Terminal, for Mac, or Ubuntu for Windows, is where one starts debugging. Let’s take a look at an application that is currently experiencing an error.

**To document a React error to the fullest, find the errors in your Command Line Interface, take some screenshots and provide these screenshots when asking for help.**&#x20;

<figure><img src="/files/gm1WZcXFB8BVrEO8u7Iy" alt=""><figcaption><p>React terminal error</p></figcaption></figure>

The error found in the CLI specifies that there is an issue:

`‘Module not found: Error: Can’t resolve ‘./Greting’ …  ERROR in ./src/App.js 6:0-33’`&#x20;

This means that something that we are importing within the App.js cannot be found, the file which we are importing from seems to be ‘./Greting’.

<figure><img src="/files/fOQZmbFnsj9u7avYaxlt" alt=""><figcaption><p>Browser error</p></figcaption></figure>

The error that we would see in the browser mirrors what we have looked at previously, this is because React is showcasing the errors that occurred during runtime. This means we probably need to take a look into the App.js as React’s error reporting is telling us where the issue originates.&#x20;

#### Further documenting && Solving the Error

<figure><img src="/files/a46hwQf1OkLiJcQb7HvO" alt=""><figcaption><p><br>Failing App.js</p></figcaption></figure>

From the code block here we can see that the component is importing ‘./Greting.js’, but if we look at the image, on the left,  we can see that the  file name is called Greeting.js. So to fix this problem, we just need to fix the import statement, such that we were importing from the correct file, then the error should be fixed.

So when we are documenting this error we should share error screenshots of the CLI tool running the application, the browser errors as well as the JavaScript components or files that are being flagged by React. In this case, the App.js.

### Document Backend Errors

When developing a backend server, it might seem operational, however, when an actual API route is consumed an error is thrown  in your CLI window where the backend application is running. This issue that is occurring might stem from the route handler, the Controller or even database. So what we will have to do is breakdown the error and and see if that can solve the issue.

To do this we would need to share the error that is being shown within our backend CLI, an example is below.

<figure><img src="/files/9L8AlCnwXOg4bPZbyaaU" alt=""><figcaption><p>CLI Error</p></figcaption></figure>

In the error above, we can see that it reads:

`‘ConnectionRefusedError … connect ECONNREFUSED 127.0.0.1:5432”`

By reading the error we can ascertain the where the issue is seeming from, in this case it seems like a Seqeulize issue has occurred, specifically that the client (our server) cannot connect to our database. There is a simple solution to this error, turn on your database. It’s possible to forget to start your database server locally or even on a deployed instance, when developing always remember to check your environments are setup before testing.<br>

You should always over share when trying to debug as it will help to provide context to people attempting to help you.

Here is an example of another error:

<figure><img src="/files/eXe9Gfg1GZyZATYG5wAT" alt=""><figcaption><p>Database Issue</p></figcaption></figure>

There are a few things that you should look out for when you are debugging your applications, some of them are highlighted above, we can see that the error is being thrown by Seqeulize, the error reads:

`‘error: relation “sightings” does not exist’`&#x20;

The error code is ’42P01’, a quick google indicates that, our database, PostgreSQL, states that error 42P01 **denotes the database query is on an undefined table**. This error usually occurs due to improper database setup, unidentified table name.

But how could this be? You’ve already setup the database, you have run npx sequelize db:migrate as well as the seed commands. So how when, I am consuming an API does it error out? Consider how Sequelize sets up your database, it will use the credentials found in ‘/config/database.js’, for database creation, migration as well as seeding data. On the other hand when querying data programatically from the application it will take whatever credentials that you have placed into the ‘/models/index.js’. Use console.log statements to ensure that your are using the correct credentials when you query data.&#x20;

The issues above were database related. You may encounter issues with other parts of your backend, such as your Controller or Router. If you do encounter an issue it would be prudent to share all of the affected files.&#x20;

Say you are trying to get some data from your database and display it on your backend, but you're receiving an error like this:

<figure><img src="/files/arXU2sETH3ZDIhhpGj3B" alt=""><figcaption><p>Backend Error, Controller</p></figcaption></figure>

This error seems to stem from the baseController file as highlighted by the image above, in this case, it would be prudent to share this file if you are asking for help. &#x20;

<figure><img src="/files/xNf7zTmrclFUgFnkDMwF" alt=""><figcaption><p>BaseController.js</p></figcaption></figure>

The error reads:

`'TypeError: Cannot read properties of undefined (reading 'findAll')'`

This indicates that there is an issue with the findAll command, in this case, we have spelt model incorrectly, replace with `this.model` and the code should be operational.

**Debugging CheckList**

* [ ] &#x20;Find any error codes&#x20;
* [ ] Document your error codes and environments they occur in
* [ ] Google the error codes to find a fix
* [ ] Check all of your environment is setup correctly
* [ ] Check that your environmental variables are correct
* [ ] Check casing throughout your application
* [ ] Check your dependancy injections
* [ ] Checkout your git commits to find a working version of your code
* [ ] Remove code line by line to check where the bug is
* [ ] Rebuild the application one line at a time checking to see if its broken

## Difficulty Levels

Rocket provides multiple levels of difficulty to accommodate different learning speeds and prior experience. Students can complete Bootcamp without attempting Comfortable, but students that complete Comfortable may have a firmer grasp of concepts. Rocket recommends completing Base for all of each day's post-class and pre-class exercises before attempting Comfortable.

### Base

Bare minimum. All students must complete Base to understand concepts.

### Comfortable

Reinforce with further exercises around same concepts. For students that wish to deepen understanding of current concepts before moving onto new ones.

### More Comfortable

Deepest exercises that Rocket offers for each concept. For students that wish to push the limits of their understanding of the current concepts.

## Project Methodology

### Ideation Phase 1

Brainstorm app ideas and solicit feedback from your section in Slack. What problem does the app solve, for whom? How does the app solve the problem? What data does the app handle? Feel free to use [Rocket's project planning template](https://docs.google.com/document/d/1klyi92bVHUKjxgD_Saou_u6yoEZFbzkvbttj2izh8xg/edit?usp=sharing) to guide you.

### Ideation Phase 2

Create the following planning docs, save them in the project GitHub repo and share them with your section in Slack for feedback. Your SL will review your planning docs with you before you begin implementation.

#### All Projects

1. User stories
2. Wireframes
3. Kanban board

#### Project 2 Onward

1. DB schema outline (NoSQL) or DB ERD (SQL)

### Scrum

Professional tech teams typically run using [Agile Scrum Methodology](https://www.atlassian.com/agile/scrum). Rocket simulates this during Bootcamp project weeks. Each course day students will share the following with their section to keep each other on track.

1. What did you do between the previous course day and today?
2. What do you plan to do between today and the next course day?
3. Do you have any blockers?

### Presentations

Students present projects in class on the last day of each module. Presentations should cover the following.

1. App demo
2. App development strategy
3. Biggest challenges faced
4. What you might do differently next time

### Post-Mortem

After each project your section leader will review your code with you 1-1. Please prepare answers to below questions before meeting. Consider recording notes; past students have found post-mortem notes helpful for resumes and portfolios.

Consider questions from both a technical and process perspective.

1. What went well? Please share a link to the specific code.
2. What were the biggest challenges you faced? Please share a link to the specific code.
3. What would you do differently next time?

### Demo Video

Record a video after each project to showcase your hard work for your portfolio and employers.

#### Requirements

1. Demo your app in a 1-2 minute video (brevity is best!)
2. Explain who your app is for, what their problem is and how they would solve their problem with your app
3. Use language that non-technical recruiters would understand
4. Record locally with Zoom with your face in the upper-right corner. Upload to YouTube and embed a video link in your project `README`.

#### Past Examples

These batches did not have a time limit; please keep yours under 2 minutes if possible.

1. [Porter (FTBC3)](https://www.youtube.com/watch?v=466AbXvMdzc)
2. [Ian (FTBC2)](https://www.youtube.com/watch?v=JjHM96XIXjs)
3. [Jit Corn (FTBC1)](https://www.youtube.com/watch?v=RxihjXRp7cQ)

## Sharing Code with Classmates

In software engineering, there are so many different ways to solve the same problem. One great way to maximise learning to have a look at how your friends completed the same exercises!

### Part 1: Sharing your solution

1. To start off any project, you will have to go to the starter repo and fork the repo.
2. Next, you will go to this new forked repo and `git clone` it down to your filesystem.
3. You are now ready to go work on your project and make all the required changes.
4. It'll be great to include a `README.md` that includes
   1. A brief description of your app
   2. How to setup and run your app
   3. For example, see <https://github.com/jiachen247/bootcamp/tree/master/M3/3-ICE-1/bigfoot-express-bootcamp>
5. Once done, you can go on to commit and push the files as per usual
   1. `git add .`
   2. `git commit -m "insert commit message here"`
   3. `git push`
6. Once the push is successfully, you should see it on your forked repo on Github.
7. Go on to make a Pull Request (from your forked repo to the original starter repo)
   1. Please name the PR "\<Your name> \<Bootcamp batch>" eg. "Jiachen FTBC6"

### Part 2: Checking out your classmates' solutions

1. To view your classmates' solutions, you can go to the starter repo and click the Pull Request (PR) tab.
2. Next, you search for your bootcamp batch (eg. FTBC6) and all your classmates PRs should be listed there.
   1. For example, see <https://github.com/rocketacademy/html-noodles-bootcamp/pulls?q=is%3Apr+is%3Aopen+FTBC6>
3. You can then view their code under the File Changes tab in the PR to view all the changes they have made.
4. To run and build their project locally, you can click on their forked repo in the PR and `git clone` it down as usual to run the project.
5. Once cloned, you can follow the README to setup and run the app!

## Peer Code Review

Occasionally we will review each others' code to learn from each other. Start by reviewing your partner's code individually, before discussing the review in pairs.

### Part 1: Individual

1. Clone partner's code
2. Read partner's code
   1. How does it work?
   2. How is it different from my implementation?
   3. What can I learn from this?
3. Run partner's code
   1. If you're not sure how certain code might behave, run it. Feel free to edit the code to verify your understanding.
4. Complete code review on partner's GitHub pull request to help them improve

### Part 2: In Pairs

1. Review learnings from individual code reviews
2. Pair program on 1 person's code to get a working version. The person with the weaker understanding of the current concepts should be the driver. For more info on pair programming, read [Rocket's primer on pair programming in Coding Basics](https://basics.rocketacademy.co/course-logistics/course-methodology/course-components#pair-programming).


# Required Software

## Introduction

This document outlines required software for Coding Bootcamp. Please install this software before starting the course unless instructed otherwise.

## Complete Fundamentals setup

1. Please install the latest version of Windows or MacOS that your computer supports.
2. If you haven't already, please obtain and install [Fundamentals required hardware, software and accounts](https://fundamentals.rocketacademy.co/course-logistics/required-hardware-and-software).

## \[Windows Only] Install Windows-specific software

### Install and setup Windows Subsystem for Linux (WSL)

WSL allows us to run the Linux operating system on Windows machines. We do this because most programming uses Unix-based operating systems, of which MacOS is a descendant. Most SWEs that use Windows do their work in WSL to maximise compatibility between their work and work done on Linux machines. Before installing WSL, update Windows to the latest version.

1. Install WSL [here](https://docs.microsoft.com/en-us/windows/wsl/install-win10).
2. Install the latest version of Ubuntu [here](https://apps.microsoft.com/store/detail/ubuntu-22041-lts/9PN20MSR04DW?hl=en-sg\&gl=sg). Ubuntu is a popular version of the Linux operating system.
3. Run `sudo apt install build-essential` in Ubuntu in WSL to install standard libraries Ubuntu needs to further install common packages.
4. Run `sudo apt-get install ca-certificates` in Ubuntu in WSL to get SSL verification certificates on Ubuntu for Ubuntu to communicate with VS Code on our computer.

### Integrate VS Code with WSL

1. Install the [VS Code Remote Development extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack) to enable VS Code to integrate with WSL.
2. Click the Remote Development extension icon in the bottom left corner of VS Code. A pop up will appear with a list of options. Click the first option "Remote-WSL: New Window" for the default distro.

You will see a notification "Starting VS Code in WSL...". This means VS Code is setting up a server inside WSL for the first time. Once installed, the VS Code of your Windows OS will sync automatically with the VS Code of your Ubuntu OS, and the VS Code terminal will show the Ubuntu terminal.

## \[Mac Only] Install Mac-specific software

### Install Homebrew

Follow instructions at [https://brew.sh/](https://brew.sh) to install Homebrew.

Homebrew is a package manager for MacOS that provides a single source of truth for which packages and package versions are installed. This is typically only relevant to command line packages; We typically do not install GUI applications via Homebrew.

Homebrew typically manages OS-specific packages, e.g. `node`, and not application-specific packages, e.g. `react`. Application-specific packages are typically managed by application-level package managers such as `npm` or `pip`. Application-specific packages are typically bundled and deployed together with an application, regardless of where those applications are running.

## Install and configure Git

### Install Git

{% tabs %}
{% tab title="Windows" %}
Open an Ubuntu terminal in VS Code and run the following commands separately.

```bash
sudo apt-get update
```

```bash
sudo apt-get install git
```

```bash
# Verify correct installation by checking Git version
git --version
```

{% endtab %}

{% tab title="MacOS" %}
1\. Download and install Git for MacOS

```
brew install git
```

2\. Verify Git is installed by running `git --version` in the [VS Code terminal](https://code.visualstudio.com/docs/editor/integrated-terminal). This should print out a version number on the next line, e.g., `git version 2.9.2`.

```
git --version
```

3\. Download and install the [Git Credential Manager](https://github.com/microsoft/Git-Credential-Manager-Core/releases/download/v2.0.498/gcmcore-osx-2.0.498.54650.pkg)

{% hint style="warning" %}
To install the Git Credential Manager you may need to allow "unidentified developer apps". Don't worry, Git Credential Manager is created by Microsoft. [Instructions here](https://support.apple.com/en-sg/guide/mac-help/mh40616/mac).

If you are using a company computer for this course you may not be able to override the security settings. You may need to [create a personal access token](https://docs.github.com/en/github/authenticating-to-github/keeping-your-account-and-data-secure/creating-a-personal-access-token) instead.
{% endhint %}
{% endtab %}
{% endtabs %}

### Personal Access Tokens&#x20;

### Configure Git and GitHub

When using the HTTPS protocol on GitHub to retrieve repository information you will need to develop a personal access token on your GitHub account, you will then be able to use this token to authenticate your request. To create a personal access token please follow this set of [documentation](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token).

After you have created the personal access token be sure to save it in a safe spot as it will be required when authenticating requests to the GitHub servers. You will be prompted to pass your GitHub username and password when trying to push to repositories, use your Personal Access Token in place of your password.&#x20;

#### Configure Git default branch

Set the default Git branch to `main` as per GitHub's (and Rocket's) latest convention. Some older versions of Git may still use `master` as the default branch name.

```bash
git config --global init.defaultBranch main
```

#### Configure Git default editor

1. Follow instructions [here](https://stackoverflow.com/a/39604469) to enable the `code` command in terminal to open VS Code.
2. Set the default Git code editor to VS Code to avoid Git's default command line editor Vim, which requires learning Vim-specific keyboard shortcuts. We may need to use Vim on remote servers as SWEs, but to keep things simple during Bootcamp we will stick to VS Code.

```shell
git config --global core.editor "code --wait"
```

#### Configure Git and GitHub Credentials

Set your GitHub account credentials on your computer through the command line. This will enable us to interact with GitHub via the command line, which we will do a lot. Please replace `<YOUR_GITHUB_USERNAME>` and `<YOUR_GITHUB_EMAIL>` with your GitHub username and email.

```bash
git config --global user.name "<YOUR_GITHUB_USERNAME>"
```

```bash
git config --global user.email "<YOUR_GITHUB_EMAIL>"
```

Type `git config -l` into the terminal to verify configuration success. If you see `user.name` and `user.email` in the output, we succeeded. If you see a `:` at the bottom of the output, you may need to press `Enter` until you see the lines starting with `user.name` and `user.email`.

After configuring your GitHub credentials you will be able to access GitHub repositories and make requests, however you will be prompted for your username and password every single request. While this level of security is brilliant for companies it can be frustrating for the developers. To make your lives a tad easier you can run these commands in your CLI in order to save your credentials into the environment.

```bash
git config --global credential.helper store
```

```bash
git config --global credential.helper cache
```

After doing these commands you may need to go through git flow once before it has saved your credentials (including your personal access token, which should be used as a password when prompted for username and password.

## Install Node.js

{% tabs %}
{% tab title="Windows" %}
Open an Ubuntu terminal in VS Code and run the following commands separately.

```bash
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
```

```bash
sudo apt-get install -y nodejs

```

{% endtab %}

{% tab title="MacOS" %}
Install Node.js using Homebrew using the following commands. `install` installs the package and `link` makes the `node` command accessible in our terminal. Run these commands separately.&#x20;

```
brew install node@18
```

```
brew link node@18
```

{% endtab %}
{% endtabs %}

## Install Code Formatters

### Install Prettier

Prettier is a code formatter that will auto-format our code and make it more readable when we save our files.

1. Install the Prettier extension for VS Code [here](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode).

### Install ESLint

ESLint is a JavaScript code linter that helps us detect functional errors in our code prior to running it.

1. Install ESLint on your computer by running `sudo npm i -g eslint` from the terminal in VS Code. Enter your computer's password if prompted.
2. Install the ESLint VS Code extension [here](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint).

### Set VS Code formatting settings

1. Open VS Code and open the command prompt with `Ctrl+Shift+P` on Windows or `Cmd+Shift+P` on Mac
2. Start typing `Preferences: Open Settings (JSON)` and select this option when you see it in the search dropdown. VS Code should open a JSON settings file.
3. Replace the contents of the file with the code below
4. Save the settings file
5. Restart VS Code to apply settings

{% code title="settings.json" %}

```json
{
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.formatOnSave": true,
  "editor.formatOnPaste": true,
  "editor.tabSize": 2,
}
```

{% endcode %}

## Setup folder structure for Coding Bootcamp

Rocket recommends the following folder structure to keep ourselves organised during Bootcamp.

{% hint style="warning" %}
Name files and folders in kebab-case, e.g. `new-file.txt`, lowercase and hyphenated for ease of use on the command line. We do not recommend naming files and folders with spaces in names because we will need to enter special characters in the terminal to escape the space character when referring to these files.
{% endhint %}

{% hint style="danger" %}
Please do not store code in folders synced to cloud storage such as Google Drive or Apple iCloud. This will cause issues during Bootcamp, such as package installations running slowly or unnecessary extra files committed to GitHub.
{% endhint %}

1. Store all Bootcamp code in a folder called `bootcamp`.
2. Within `bootcamp`, create a folder `m1` for Module 1 and store all Module 1 exercise code there in exercise-specific folders. Our Project 1 repo folder can also go inside `m1`.
3. Make 3 copies of `m1` within `bootcamp` and rename them `m2`, `m3`, and `m4`, 1 folder for each module in Bootcamp.

## Sign up for accounts

We will use the following software accounts during Bootcamp.

1. [Codecademy](https://www.codecademy.com/)
2. [LeetCode](https://leetcode.com/)
3. [HackerRank](https://www.hackerrank.com/)

## Extra Reading

#### GitHub and SSH

Another way developers are able to authenticate requests to GitHub is to create and use an SSH key on their personal machines. This SSH key acts as a unique signature that can be linked to your GitHub account online, essentially creating a connection between your machine and GitHub when used. SSH keys require a little more setup than using HTTPS but they will not prompt you for authentication every single request.

#### Setting up SSH&#x20;

1. &#x20;You will need to check for existing SSH keys on your machine, please follow these [docs](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/checking-for-existing-ssh-keys).&#x20;
2. If you do not have you then you will need to generate a new SSH key please follow these [docs](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent).
3. Following this you will need to add the new SSH key into your GitHub account online please follow these [docs](<https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account >).


# LinkedIn Education Badge

## Introduction

Software Engineering Bootcamp students can add Rocket Academy to the Education sections of their LinkedIn profiles. Here are instructions.

## 1. Go to your LinkedIn profile page and click "**Add profile section"**

![](/files/07uRBm60XX8LRlDX91y3)

## 2. Click "Education" to add a new education badge

![](/files/ExTW1riypa2eR2zqyupY)

## 3. Fill in Rocket's Coding Bootcamp course details

1. Notify network
   1. On
2. School
   1. Rocket Academy
3. Degree
   1. Software Engineering Bootcamp
4. Start Date
   1. The month you enrolled in Rocket's Bootcamp
5. End Date
   1. The month you graduated from Rocket's Bootcamp
6. Description
   1. Full-stack software engineering and algorithms. Review my portfolio here: \<PORTFOLIO-LINK>

![](/files/s4grZUq8Mgnu0hg3ugvc)

## 4. Admire your hard-earned education badge 🚀

If needed, move the new education badge to the top of your Education section.

![](/files/wOrFrFBQdciehYrQBoa7)


# General Reference


# Naming, Casing, and Commenting Conventions

Naming, casing, and commenting are critical to software engineering because they help us communicate what our code does, preventing miscommunication and bugs. The following are Rocket Academy's naming, casing, and commenting conventions.

## Naming

### General

In general, variable names should be as specific as needed to prevent miscommunication. For example, for a card game with 2 representations of a card, one the card's HTML element and one a JS Object containing the card's name, suit, and rank, we might name the former `cardElement` and the latter `cardMetadata`. Avoid naming either variable `card` to prevent miscommunication.

Avoid using shorthand in variable names that might be common in [SMS language](https://en.wikipedia.org/wiki/SMS_language), because such terminology may not be universal and can cause confusion and bugs. Strive for precision and concision, prioritising the former where necessary. For example, in Singapore it may be common to use the letter "n" as an abbreviation for "and" and the letter "w" as an abbreviation for "with". Avoid these in variable names because they may not be universal.

### Functions

Function names should start with a verb. This is to distinguish functions from data that might take a similar name. For example, the function `getRandomNum` may return a random number that gets stored in a variable `randomNum`.

### Booleans

Boolean variable names should start with a question word. This is to clearly communicate that this variable stores a boolean. For example, `isGameOver` and `hasPlayerWon` would be preferred boolean variable names than `gameOver` and `playerWon` because the former more explicitly store booleans.

### Event Handlers

By convention, we typically name callback functions that handle events with the prefix `handle` and suffix event type. For example, we would name the callback function for an `onClick` event `handleClick`.

## Casing

### Variables

By default, JavaScript uses [camelCase](https://en.wikipedia.org/wiki/Naming_convention_%28programming%29#Examples_of_multiple-word_identifier_formats) for variable names. Treat acronyms like regular words and use [camelCase for the acronym](https://stackoverflow.com/questions/15526107/acronyms-in-camelcase#:~:text=When%20using%20acronyms%2C%20use%20Pascal,in%20identifiers%20or%20parameter%20names) for greater readability, e.g. `cardHtmlElement` instead of `cardHTMLElement`.

### Constants

Sometimes we have variables that are constant in our program and used in multiple places, for example number of starting points in a game. To communicate clearly what these constants are and prevent bugs due to string or number misspelling, we often store these variables in "constant" variables, typically near the top of our file or in a separate `constants.js` file.

Constants are typically cased with [SCREAMING\_SNAKE\_CASE](https://en.wikipedia.org/wiki/Naming_convention_%28programming%29#Examples_of_multiple-word_identifier_formats) by convention, e.g. `NUM_STARTING_POINTS`.

### Environment Variables

SCREAMING\_SNAKE\_CASE. `MY_ENV_VAR`.

### File Names

There is no definitive file naming case convention for JS. Rocket Academy prefers [kebab-case](https://en.wikipedia.org/wiki/Naming_convention_%28programming%29#Examples_of_multiple-word_identifier_formats) because it's easier to navigate between words than [snake\_case](https://en.wikipedia.org/wiki/Naming_convention_%28programming%29#Examples_of_multiple-word_identifier_formats), where word processors do not consider underscores to be word separators. Some teams use CamelCase for React component file names; this is subjective so long as we are consistent.

### HTML Tags

Lowercase. E.g. `<div>`

### HTML Attributes

Lowercase kebab-case. E.g. `<div my-attr="lowercase">hello</div>`

### React Components

UpperCamelCase. E.g. `MyReactComponent`

### CSS

IDs and classes in kebab-case. Prefix related classes with common prefix for organisation, e.g. `.card-image` and `.card-text`.

### Git Branches

Git branches are typically named with kebab-case, e.g. `my-new-feature`.

### URLs

URL entities that consist of multiple words are separated by hyphens. For example, `www.mysite.com/my-url-entity`.

### SQL Table and Column Names

SQL table names should be plural and in snake\_case, and column names should be singular and in snake\_case. SQL is case-insensitive, and SQL commands such as CREATE and WHERE are often capitalised, thus lowercase is preferred for column names. Underscores are preferred over hyphens to separate words because hyphens are special characters in some SQL implementations.

## Commenting

### Inline Comments

1. Comments should only exist to clarify code
2. Start comments with a capitalised word like we would an English sentence
3. Inline comments go directly above the line or lines they are commenting on

### Function-Level Comments

For function-level comments in JS, consider using [JSDoc format](https://jsdoc.app/about-getting-started.html#adding-documentation-comments-to-your-code) for clearer identification of functions and what they do. JSDoc is a standard format for JS comments, as well as a tool that auto-generates HTML pages that document code files.

```javascript
/**
 * A function that sums numbers
 * @param  a {number} number to add together
 * @param  b {number} number to add together
 * @return {number}   a and b added together
 */
var add = function (a, b) {
  return a + b;
};
```

The `@` symbol in JSDocs signifies a "tag"- some structure of the code to document. In Rocket Academy JavaScript documentation we will be almost exclusively using only the `param` and `return` tags in JSDoc formatted comments. See the full list of tags [here](https://jsdoc.app/index.html#block-tags).


# VS Code Tips

Tips for using VS Code

## Comment Out Multiple Lines at Once

Sometimes we wish to enable or disable certain segments of our code for quick testing. The easiest way to do this is to "comment out" the code we want to disable by turning it into comments, making our JavaScript runtime ignore those lines of code.

Rather than adding `//` to the start of each line manually, VS Code has a shortcut that allows us to comment out multiple lines simultaneously. To do this, select all lines we wish to comment out, then use the keyboard shortcut `Ctrl+/` on Windows, or `Cmd+/` on Mac.

## Editing a Variable Name in Multiple Places Concurrently

Sometimes we want to change the name of a variable in our code, a common practice in [refactoring](https://en.wikipedia.org/wiki/Code_refactoring). If that variable is used in multiple places, we may be tempted to edit each instance individually. Luckily VS Code has a convenient feature that allows us to edit all instances of the same variable simultaneously, saving time and our fingers.

### Within a Single File

1. Move your cursor to the first instance of the variable
2. Press/hold `Ctrl+D` on Windows or `Cmd+D` on Mac until all instances of that variable are selected
3. Use left or right arrow keys to enable cursors on each instance of that variable and edit them simultaneously

### Across Multiple Files

VS Code has a [search and replace feature](https://code.visualstudio.com/docs/editor/codebasics#_search-across-files) that allows us to edit all instances of a given string in multiple files at once.

## Hide Minimap

The [VS Code minimap](https://code.visualstudio.com/docs/getstarted/userinterface#_minimap) is displayed by default in VS Code to show one's vertical position within a file. This may not be necessary and we can hide the minimap for more space in VS Code. Hide the minimap by toggling View > Show Minimap in the menu bar.


# Recommended Resources

Past students have found the following resources helpful.

## Books

1. [Cracking the Coding Interview](https://github.com/Avinash987/Coding/blob/master/Cracking-the-Coding-Interview-6th-Edition-189-Programming-Questions-and-Solutions.pdf)
2. [Data Structures and Algorithms in Python](https://github.com/cjbt/Free-Algorithm-Books/blob/master/book/Data%20Structures%20%26%20Algorithms%20in%20Python.pdf)
3. [Clean Code](https://github.com/dev-marko/clean-code-book/blob/master/Clean%20Code%20\(%20PDFDrive.com%20\).pdf)
4. [You Don't Know JS](https://github.com/mohitd648/books/blob/master/you-don-t-know-js.pdf)
5. [SWE at Google](https://res.infoq.com/articles/software-engineering-google/en/resources/software_engineering_at_google_extract-1622201647282.pdf)

## Videos

1. [Fireship: 100-second explainer videos](https://youtube.com/playlist?list=PL0vfts4VzfNiI1BsIK5u7LpPaIDKMJIDN)

## Interview Guides

1. [Tech Interview Handbook](https://www.techinterviewhandbook.org/)


# 0: Foundations

Module 0 covers languages and tools we will need across Coding Bootcamp and as a software engineer. We will learn Module 0 content on as as-needed basis during Bootcamp.


# 0.1: Command Line

## Learning Objectives

1. The command line is a text interface for manipulating our computers
2. Navigate folders and display folder contents in the command line
3. Create new folders and files in the command line
4. Rename or delete folders and files in the command line

## Introduction

The command line, also known as "terminal" is a text-based computer interface. We will use the command line to manage files, use Git version control and run Node applications. Using the command line is separate from writing application code, though we will need the command line to build apps effectively.

{% hint style="warning" %}
If you are a Windows user, please use the VS Code terminal connected to Ubuntu in WSL. The Windows Command Prompt runs PowerShell by default which is not compatible with Unix-based commands that most software engineers use. See [Windows Command Line Setup](/logistics/required-software#install-and-setup-windows-subsystem-for-linux-wsl) for details.
{% endhint %}

## Common Commands

Below, we have listed some of the most commonly used terminal commands that software engineers use. To learn more about these commands, google "man" followed by the command name to get the "manual" page for the command (eg. to learn more about "pwd", simply enter "man pwd" into google).

{% hint style="info" %}
**Tab Complete**

The command line will autocomplete file and folder names if we press `tab` after starting to type their names. This can save us a lot of typing!
{% endhint %}

<table><thead><tr><th width="150">Command</th><th width="150">Meaning</th><th>Sample Usage</th><th>Explanation</th></tr></thead><tbody><tr><td><code>pwd</code></td><td>Present working directory</td><td><code>pwd</code></td><td>Retrieve the "absolute path" of the current folder (directory). <br><br>Absolute means relative to the root folder of your hard drive.</td></tr><tr><td><code>ls</code></td><td>List</td><td><code>ls</code></td><td>List the files and folders in the current folder</td></tr><tr><td><code>cd</code></td><td>Change directory</td><td><code>cd rocket/project1</code></td><td>Move to the specified folder. <br><br>If we do not specify a folder, <code>cd</code> will move us to the current user's home folder.<br><br>To move to the parent folder, use <code>cd ..</code>. The 2 dots are a special path referencing the parent folder.</td></tr><tr><td><code>mkdir</code></td><td>Create folder</td><td><code>mkdir components</code></td><td>Create a new folder at the specified path</td></tr><tr><td><code>cp</code></td><td>Copy</td><td>File: <code>cp App.js newComponent.js</code><br><br>Folder: <code>cp -r components components-new</code></td><td>Copy the contents of the first file to the second, overwriting contents of the second if any. <br><br>Use <code>cp -r</code> (recursive flag) to copy folders.</td></tr><tr><td><code>mv</code></td><td>Move</td><td><p>Move: <code>mv App.js components</code></p><p>Rename: <code>mv App.js index.js</code></p></td><td><p>Move the 1st argument to the 2nd argument. <br><br>If the 2nd argument is a folder, move the 1st argument inside the 2nd argument. </p><p></p><p>Otherwise, rename the 1st argument to be the 2nd argument.</p></td></tr><tr><td><code>rm</code></td><td>Remove</td><td>File: <code>rm unnecessary-file.txt</code><br><br>Folder: <code>rm -r unnecessary-folder</code></td><td><p>Delete a file or folder. This is irreversible and there is no trash folder. <br></p><p>Be very careful, and if you delete the root folder <code>/</code> you may have to reformat your computer.</p></td></tr></tbody></table>

## Common Special Paths

The following paths are shortcuts to common locations and are often used in folder navigation.

<table><thead><tr><th width="150">Path</th><th>Meaning</th><th>Sample Usage</th><th>Explanation</th></tr></thead><tbody><tr><td><code>/</code></td><td>Root, i.e. the highest-level folder on our computers</td><td><code>cd /Users/joe/rocket/project1</code></td><td>All absolute paths begin with the root folder <code>/</code></td></tr><tr><td><code>~</code></td><td>Home, i.e. the logged-in user's home folder</td><td><code>cd ~</code></td><td><code>~</code> is an alias for <code>/Users/username</code>, where <code>username</code> is the username of the logged-in user</td></tr><tr><td><code>..</code></td><td>Parent folder</td><td><code>cd ..</code></td><td>Every folder has a hidden link <code>..</code> that references the parent folder. <code>cd ..</code> changes directory to the parent folder without having to reference the name of the parent folder.</td></tr><tr><td>.</td><td>Current folder</td><td><code>mv components/App.js .</code></td><td><code>.</code> is most commonly used to move files or folders from elsewhere to the current folder</td></tr></tbody></table>

## Exercise

Run each of the above commands with local files and folders. Verify file and folder changes in Ubuntu File Manager or MacOS Finder.

## Additional Resources

The following is a command line tutorial from a previous version of Rocket's Coding Basics course.&#x20;

{% embed url="<https://youtu.be/iRnFyFMvH1o>" %}


# 0.2: Git

## Learning Objectives

1. All software engineers use version control, and Git is the most popular version control system
2. Version control allows us to track which versions of our code have which features, and to write code in teams while avoiding potential conflicts.
3. Know how to add, and commit, files to "commits", i.e. versions of our code
4. Know when to commit changes during project development

## Introduction

All software engineers use version control to manage and review project versions and to write code in teams. Git is the most popular version control system.

Version control is not strictly necessary to create programs, but it makes software development easier by reducing the fear of breaking code. If we break code when using version control, we can compare our changes to the last working version, easily find bugs to fix, or even rolling back to the last working version if needed.

In this submodule we will learn how to create code versions, more commonly known as "commits".&#x20;

We will continue to learn Git techniques as we progress through Bootcamp.

## Git Terminology

| Term         | What it is                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Repository   | A Git repository, also known as a "repo", is a folder that contains code for a given project. We typically have separate repos for each project, such that each repo only tracks changes to the code for its own project.                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| Commit       | A Git "commit" is a version of our code that records a set of changes to 1 or more files. These changes can include changes within existing files, but also include addition, deletion, renaming and moving of files. Each Git repo stores a time series of commits since the creation of the repo.                                                                                                                                                                                                                                                                                                                                                                |
| Staging area | <p>Git requires us to "stage" changes before we commit them. This allows us to easier control which changes go in which commit, especially if we have made multiple changes that belong to multiple features.<br><br>For example, I may have renamed a word across my app for a branding change (Feature A) and added payment functionality (Feature B) all at once, but I do not wish to commit them together because they are separate features. With Git's staging area I would be able to only stage and commit the changes for 1 feature at a time, allowing me to keep Feature A if there is a bug that requires rollback with Feature B and vice versa.</p> |

## Git Commands

The command line is the most common and canonical way to manipulate Git. There are GUI tools, but software engineers often work with Git on remote servers that are only accessible via command line.

The following are common Git commands we will use as software engineers.

| Command                          | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| -------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `git clone <target-repo-url>`    | Download a copy of the target repo into the current folder.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `git status`                     | View which files have changed since the latest commit, and which files are in the staging area.                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `git diff <filepath>`            | <p>Review changes made in each file at given file path since latest commit. If file path not specified, show changes made to all files in repo.</p><p>This allows us to verify we made intended changes. If changes are longer than window height, use <code>Enter</code> to browse downward. Press <code>q</code> to exit.</p>                                                                                                                                                                                                                    |
| `git add <filepath>`             | <p>Stage files in specified file path for commit by adding them to the staging area. Files added to staging are not committed yet.<br><br>Often (but not always) we will want to add all changed files to staging. We can do this with <code>git add .</code>, where <code>.</code> is an alias for the current folder.</p>                                                                                                                                                                                                                        |
| `git commit -m <commit-message>` | <p>Commit all files in staging to a new Git commit. The <code>-m</code> flag, which stands for "message", allows us to enter a mandatory commit message in the command line instead of in an editor. Commit messages should be short and descriptive, describing what changed and why.<br><br>Running <code>git commit</code> without the <code>-m</code> flag may bring us to Git's default editor, which we should have set to VS Code. If we get stuck in a command line editor, type <code>:q</code> and press <code>Enter</code> to exit.</p> |
| `git log`                        | <p>View a list of all commits in this repo. Use <code>Enter</code> to scroll downward and <code>q</code> to exit if output longer than screen height. <br><br>You can use the <code>--oneline</code> flag for a more concise list of commits.</p>                                                                                                                                                                                                                                                                                                  |

## When to commit changes?

1. We should strive to keep commits relatively small so it is easy for our team to review the changes in each commit
2. We should strive to only commit code when it is in a state that others would find useful; not in a broken state or with commented-out scratch code

## Exercise: Git Poetry

The following exercises should help familiarise you with Git. We use text instead of code, but the Git functionality is the same. You may wish to have 3 windows open on your screen: VS Code, the Git Commands table above, and the following instructions.

1. Open today's folder in terminal and create a folder with the command `mkdir`
2. `cd` into the folder, and initialise it as a git repo using the command `git init`
3. Create a text file in the command line using `touch spring-poem.txt` and open it in VS Code with `code spring-poem.txt`
4. Write a poem about spring (or anything) in `spring-poem.txt` and save the file
5. Stage and commit `spring-poem.txt` with `git add .` and `git commit -m`
6. Edit our poem to reference leaves (or anything). Stage and commit the edits
7. Add a 2nd poem about winter (or anything) in a new file `winter-poem.txt`
8. Add a title to our spring poem above the poem in the file
9. Commit the latest changes to `winter-poem.txt` and `spring-poem.txt` in 2 commits by adding 1 of them to the staging area and committing before adding the other
10. Use `git log` to review commits in our repo

## Additional Resources

1. [Intro to Version Control by Git](https://git-scm.com/book/en/v2/Getting-Started-About-Version-Control)
2. (Below): Intro to Git video from a prior version of Rocket Academy's Coding Basics course

{% embed url="<https://youtu.be/GudllO59HJQ>" %}
Intro to Git video from a prior version of Rocket's Coding Basics course
{% endembed %}


# 0.2.1: Branches

## Learning Objectives

1. Git Branches allow us to develop features independently of "production" code to avoid affecting what our teammates and users see before we are ready.
2. How to create a new branch
3. How to move between branches
4. How to merge 1 branch to another and resolve merge conflicts

## Introduction

A Git Branch is an independent series of commits. Every Git repo starts with a single branch, typically `main`, which we can imagine to be a linear series of commits.

![Every repo starts with the main branch by default](/files/ayD8zyOGoFKBmvUv6ZFA)

Using multiple branches allows software engineers to develop new features based on production code in `main` without affecting `main`, even after pushing to GitHub. We typically refer to non-`main` branches as "feature branches". Feature branches can be for changes as small as a typo and as large as new products.

Feature branches are independent series of commits that typically "branch" from `main` , and merge back into  `main` after we have completed and tested the new feature.

![Create and work on a feature branch when working on a new feature](/files/U2YsYyvrezLiDdoB5PXG)

We can delete feature branches after merging them to `main`.

![Git state after merging feature branch to main. All commits from feature branch are copied to main, and Git adds an extra "merge commit" to resolve differences.](/files/WufsltsXSWOIiuXDH0gV)

At large tech companies, 1000s of engineers can be working on independent feature branches that branch from `main` and merge back to `main` at different points in time.

## Create a branch

Create new branches with `git checkout -b`. `git checkout` is the command to switch, or "checkout" branches, and the `-b` flag creates a new branch and checks it out. Branch names use kebab-case (lowercase with hyphens between words) by default, and we will use `my-feature` as our example branch name.

```
git checkout -b my-feature
```

Verify we are on the new `my-feature` branch with `git branch`.

```
react % git checkout -b my-feature
Switched to a new branch 'my-feature'
react % git branch
  main
* my-feature
react %
```

Now we can make commits on `my-feature` that build on the state of `main` when we created `my-feature`. Changes on `my-feature` will not affect any other branch in our repo.

## Change branch

While working on feature branches we may wish to periodically checkout other branches such as `main` to verify our changes are still compatible with theirs. To change back to the `main` branch, run `git checkout main`. We may also wish to `git pull` when on `main` to pull any new changes from GitHub to `main`. Run `git checkout my-feature` to go back to the `my-feature` branch.

## Merge feature branch to `main`

Once done with our feature on our feature branch, we can merge our changes to `main` for teammates and users to use. When working independently we can perform the merge locally, but when working in a team we typically perform the merge via GitHub to give teammates a chance to review our changes through a "pull request".

### Merge locally

1. Checkout the branch we want to merge into. For example, if we want to merge changes on our feature branch to `main`, checkout `main`.
2. Run `git merge` followed by the source branch name, e.g. `git merge my-feature`.
3. Git will combine commits from both branches and create a "merge commit" to resolve any differences. Run `git log` to view the merge commit and verify merge success.
4. Delete the feature branch locally with `git branch -d` followed by the feature branch name, e.g. `git branch -d my-feature`.
5. Once ready, push latest changes in `main` to GitHub.

### Merge on GitHub

1. Checkout and verify we are on our feature branch with `git branch`
2. Run `git push` to push latest commits from our feature branch to GitHub. If this is our first time pushing this feature branch to GitHub, we may have to run `git push --set-upstream origin` followed by our feature branch name, e.g. `git push --set-upstream origin my-feature`.
3. See instructions in [0.3.1: Pull Requests](/0-foundations/0.3-github/0.3.1-pull-requests) for how to create and merge a pull request in GitHub.

We may see the following output when pushing a feature branch to GitHub for the first time with `git push`. To resolve, enter the command Git suggests: `git push --set upstream origin my-feature`, where `my-feature` is the name of our feature branch.

{% code title="Git Push failure first time pushing feature branch to GitHub" %}

```
react % git push
fatal: The current branch my-feature has no upstream branch.
To push the current branch and set the remote as upstream, use

    git push --set-upstream origin my-feature

react % git push --set-upstream origin my-feature
Total 0 (delta 0), reused 0 (delta 0), pack-reused 0
remote:
remote: Create a pull request for 'my-feature' on GitHub by visiting:
remote:      https://github.com/kai-rocket/react/pull/new/my-feature
remote:
To https://github.com/kai-rocket/react.git
 * [new branch]          my-feature -> my-feature
Branch 'my-feature' set up to track remote branch 'my-feature' from 'origin'.
react %
```

{% endcode %}

`upstream` refers to where our code should be hosted. `origin` refers to our GitHub repo or where we cloned our repo from. `my-feature` tells Git to create a new branch called `my-feature` in GitHub and by default push changes from the local `my-feature` branch to the GitHub `my-feature` branch.

After setting upstream once for a branch, we can run `git push` without arguments for subsequent pushes from this branch.

## Merge `main` to feature branch

In addition to merging feature branches to `main`, another common workflow is to merge latest changes from `main` into our feature branch. This minimises chances of merge conflicts when we merge our feature branch to `main`, especially if there have been big changes to `main` since we started our feature.

1. Checkout `main` with `git checkout main` and pull latest changes from GitHub with `git pull`.
2. Checkout our feature branch, e.g. `git checkout my-feature`.
3. Run `git merge main` to merge `main` into our feature branch. If we're lucky Git will merge the changes automatically. If not we will need to resolve merge conflicts manually.

## Merge Conflicts

{% embed url="<https://youtu.be/56B7MOgm_CE>" %}
Demo of how merge conflicts happen and how to resolve them
{% endembed %}

### What are merge conflicts and why do they happen?

Merge conflicts are situations when Git cannot automatically merge changes from 2 branches, for example if 2 branches change the same line of code differently. We can minimise merge conflicts by actively communicating with teammates to work on different files or functions, but generally merge conflicts are a standard feature of software engineering.

VS Code highlights differences in files with conflicts. The lines surrounded by `<<<<<<< HEAD` and `=======` are changes from the branch we are on, and the lines surrounded by `=======` and `>>>>>>> main` are changes from the incoming branch.

![Git will tell us where we have merge conflicts when we enter git status after merging. Within those files, VS Code will tell us which lines are in conflict, and we can click buttons above the conflict to resolve the conflicts.](/files/hS0A7n1uqX8DsDzCjQFp)

### How to resolve merge conflicts

Once we have a merge conflict we must resolve it before writing new code, such that each commit in our commit history continues to describe a specific change. If we are unable to resolve conflicts now or merged by accident, we can abort merge with `git merge --abort`, which will revert our repo state to just before we ran `git merge`.

After Git tells us we have merge conflicts, use `git status` to confirm which files have conflicts.

Open each file with conflicts and resolve conflicts in each file by removing lines starting with `<<<<<<<`, `=======` and `>>>>>>>` and updating the code to what it should be. We can use VS Code's Accept Current/Incoming/Both Changes buttons and/or manually edit the files.

![VS Code gives us buttons above each conflict to conveniently resolve each conflict.](/files/hEtz4rSFS5snvP187IKZ)

Once we have resolved all conflicts, verify our app still works as expected. Once satisfied with our changes, `git add` the resolved files to add them to staging area for commit.

![Once we have resolved the conflict in the file we can git add to stage the file with conflicts for commit. We need to make a new commit to mark the conflict resolved.](/files/JsvRTjvUJb44cPGYt0bq)

Commit changes to finalise Git's merge commit and complete merge.

![Entering git commit after adding resolved files to staging area will open a commit message window. Save and close the file to complete commit.](/files/RCDQtec6hPszxIoVW931)

After committing, `git status` should no longer mention conflicts.

![Once we save the commit message file, we should see the commit completed.](/files/AKiJdTWqmadq0EWN23VJ)

We can verify merge success by checking commit history in Git Logs with `git log`.

![We can verify successful merge by looking at Git Logs.](/files/EU3cL4FIEUHaxzw4lOKL)

## Exercises

### Create feature branch and merge to `main` without merge conflicts

1. Create a new repo.

   ```
   mkdir poems
   cd poems
   git init
   ```
2. Create a poem about water in `water-poem.txt`. Commit this file to the repo.
3. Create and checkout a new branch to edit the water poem.

   ```
   git checkout -b water-poem-edits
   ```
4. Edit the water poem and commit it to the new branch you just created.
5. List all branches.

   ```
   git branch
   ```
6. Checkout `main`.

   ```
   git checkout main
   ```
7. Verify `water-poem.txt` has reverted to the version on `main`.
8. Create a new poem about sandwiches in a new file and commit it.
9. Checkout the water poem branch.

   ```
   git checkout water-poem-edits
   ```
10. Verify the sandwich poem does not exist in the water poem branch.
11. Checkout `main` and merge the water poem edits from the water poem branch.
12. Verify `water-poem.txt` contains changes from the water poem branch.
13. Delete the water poem branch with `git branch -d water-poem-edits`.

### Resolve Merge Conflicts

1. Start from the same repo as the previous exercise.
2. Make a new branch for edits to the sandwich poem.

   ```
   git checkout -b sandwich-poem-edits
   ```
3. While on the sandwich branch, add a line to the poem and change the line that's currently there.
4. Commit the changes on the sandwich branch.
5. Checkout `main`. To create a merge conflict we will commit new changes to the same lines on the `main` branch.
6. Make a change to the sandwich poem and commit it.
7. Merge the sandwich branch into `main`.
8. We should observe a merge conflict.
9. Open the sandwich poem file to see merge conflict symbols from Git.
10. Resolve the merge conflict as per instructions above.


# 0.3: GitHub

## Learning Objectives

1. GitHub is a code-hosting website that hosts Git repos for individuals or teams to review and collaborate on
2. Know how to fork a repo on GitHub
3. Know how to clone a repo from GitHub
4. Know how to push changes to GitHub
5. Know how to pull changes from GitHub
6. Know how to view repo commit history in GitHub

## Introduction

GitHub is a code-hosting website that hosts Git repos for individuals or teams to review and collaborate on. Team members can easily review latest code changes and commit history, making software development more transparent and thorough.

## GitHub Workflow Summary

1. **Fork** repos we do not have edit access to to suggest changes or maintain our own copy
2. **Clone** repos to download local copies of GitHub repos
3. Once we have committed the changes we want locally, **push** our changes to GitHub to share them with others. Refresh the GitHub repo page to see those changes.
4. If we are working with teammates and wish to download their code while keeping local changes, **pull** their code from GitHub after committing our local changes.

## GitHub Fork

A GitHub "fork" is a copy of another GitHub repo. SWEs typically "fork" repos they do not have edit access to either to make improvements to merge back into original repos, or to create and maintain independent versions of repos. At Rocket Academy we will fork Rocket exercise repos to complete and submit assignments.

We can fork a repo by clicking the Fork button on a GitHub repo page. Once forked, we can change our copy of the repo without affecting the original.

![Click the Fork button to fork a repo](/files/mYshD9ZNtpVul6aCoomx)

![Fork menu; We typically keep the same repo name for clarity](/files/ORAkJJZzwXh6AOXzinoE) ![Forked repo; Notice the repo is now under my account](/files/sBFoOxSCuK8AAZdLgrrL)

## Git Clone

Once we have edit access to the repo we want to edit, either by forking an existing repo or [creating a new repo](https://docs.github.com/en/get-started/quickstart/create-a-repo), we can "clone" (i.e. download) that repo to our local machine to make changes to it.

Click the copy button in the Code dropdown menu on the GitHub page of the repo we wish to edit.

![Click the copy button in the Code dropdown to copy the repo link to use with git clone](/files/sUJQQxtdawtF9IuQcWx7)

Then go to terminal, `cd` to the relevant folder and enter the command `git clone <repo-url>`, where `<repo-url>` is the URL we just copied from GitHub. This will create a new folder named after the repo with the repo's contents inside.

```
bootcamp % git clone https://github.com/kai-rocket/react.git
Cloning into 'react'...
remote: Enumerating objects: 203678, done.
remote: Total 203678 (delta 0), reused 0 (delta 0), pack-reused 203678
Receiving objects: 100% (203678/203678), 173.82 MiB | 5.85 MiB/s, done.
Resolving deltas: 100% (144768/144768), done.
bootcamp %
```

Once we've cloned the repo we can make edits to it and track our changes with Git.

## Git Push

`git push` allows us to share local changes by "pushing" local commits to GitHub for others to view. Video demo below.

{% embed url="<https://youtu.be/BJojbCFfOHU>" %}
Demonstration of how to push local changes to GitHub
{% endembed %}

## Git Pull

`git pull` allows us to download new changes in a shared GitHub repo (e.g. by teammates) while keeping our local changes. Git will automatically merge downloaded and local changes, and let us know if there are "merge conflicts", for example if downloaded and local changes edit the same lines of code. We will work more with `git pull` once we start group projects.

## How to view commit history in GitHub

GitHub provides an easy way to view past changes to a repo. For example, if we are wondering which commit changed a line of code that caused a bug, we can easily find which commits changed that line, who made those commits and what other changes were in those commits.

![Click the number of commits on a repo's GitHub page to view a list of all its commits](/files/jK8mYwl98OmI13oxShA1)

![Click on any commits in the repo's commit history to view the details of that commit](/files/d1YlKWFpwoOQ4Bis74yg)

![We can review complete details of each commit in GitHub](/files/kvzFZ4XrY4esKKpEqkYg)

## Additional Resources

1. [Git and GitHub in Plain English](https://blog.red-badger.com/2016/11/29/gitgithub-in-plain-english) (blog post)
2. [Git and GitHub by The Coding Train](https://youtube.com/playlist?list=PLRqwX-V7Uu6ZF9C0YMKuns9sLDzK6zoiV) (video playlist)
3. (Below) Intro to GitHub video from prior version of Rocket's Coding Basics course
4. (Below) GitHub Fork video from prior version of Rocket's Coding Basics course
5. (Below) GitHub Repo Browsing video from prior version of Rocket's Coding Basics course

{% embed url="<https://www.youtube.com/watch?v=dn7r4333c4g>" %}
Intro to GitHub video from prior version of Rocket's Coding Basics course
{% endembed %}

{% hint style="warning" %}
In the below GitHub Fork video we demonstrate `git push origin master`, but for most purposes `git push` will suffice.
{% endhint %}

{% embed url="<https://youtu.be/uMNcnLWTmZU>" %}
GitHub Fork video from a prior version of Rocket's Coding Basics course
{% endembed %}

{% embed url="<https://youtu.be/a-flBCpOmBU>" %}
GitHub Repo Browsing video from prior version of Rocket's Coding Basics course
{% endembed %}


# 0.3.1: Pull Requests

## Learning Objectives

1. Pull requests are requests to merge, aka "pull" changes from 1 branch to another. They are typically used for code review before merging feature branches to the `main` branch.
2. Know how to create pull requests in GitHub
3. Know how to leave comments on and merge pull requests in GitHub

## Introduction

A GitHub [**pull request**](https://docs.github.com/en/free-pro-team@latest/github/collaborating-with-issues-and-pull-requests/about-pull-requests) (PR) is a request to merge or "pull" changes from 1 branch on GitHub to another. PRs are most commonly used for code review, where SWEs share PRs for peer review before merging that code to a `main` branch. Reviewers can comment on individual lines in the PR and request changes before the code is merged. Rocket uses PRs for student code submission and review.

![A pull request on Facebook's React repo](/files/41EVD8J0BsUrUVZ3cmXs) ![Reviewers can leave comments on pull requests to acknowledge good work and request changes](/files/w3h7PdlXHXkd6XeUu9in)

## How to create, comment on and merge pull requests

Below is a demo video for how to create, comment on and merge pull requests.

{% embed url="<https://youtu.be/-m5ShISXdg8>" %}
Demo video on how to create, comment on and merge pull requests
{% endembed %}

To create a pull request to merge a change from a feature branch to `main` (or any other branch), first push the latest changes from that feature branch from our local repo to GitHub.

Once the latest changes on that feature branch are in GitHub, we can navigate to the "Pull requests" tab in our repo's GitHub page and click "New pull request".

![Navigate to Pull requests tab and click New pull request to initiate new PR](/files/uM7W1FcDNyLG0yX9jLKj)

Verify we are merging the correct source and target branch, and correct commits and code changes. Once verified, click "Create pull request".

![Verify we have the correct branches and commits before creating pull request](/files/DziQ6qa0vH2hNKece98J)

Leave a descriptive title and description for reviewers, then click "Create pull request".

![Leave descriptive title and description for each PR](/files/PedD7gBxe9dwnHZB9MXj)

If you are a reviewer or want to leave comments for your reviewer, hover over the relevant line of code and click the "+" icon to leave a comment on that line. To comment on multiple lines, click and drag the "+" icon over the relevant lines.

![Click "+" icon to comment on 1 or more lines in the PR](/files/K2d29R8kHOzcOtvDIyAn)

Once reviewers have approved the PR, click "Merge pull request" in the PR's Conversation tab to merge the relevant branches and close the PR.

![Once reviewers have approved, merge the PR to merge relevant branches and close the PR](/files/b3mlrD7t9vJYNLGRxtnm)

After merging the PR, we should see the merged code in the target branch, in this case `main`.

![Merged PRs have a "Merged" status](/files/3hRKcFkphyYdMdS4YgTx) ![After merging, target branch should contain the latest changes](/files/6DCKekpctkICetut7f7l)


# 0.4: JavaScript


# 0.4.1: ES6

## Learning Objectives

1. Know that ES6 is today's de-facto JavaScript language version

## Introduction

[ES6](https://www.w3schools.com/js/js_es6.asp) is today's de-facto JavaScript language version. JS began with few features and has since included many more. Every coding language has maintainers that release new versions over time.

Browser compatibility is a primary consideration for JS version because frontend JS runs in our users' browsers, whose versions we do not control. Older browsers may not be able to run newer versions of JS. This is why later JS versions such as ES7 are not yet widely-adopted. We can still use ES7 with "compilation" programs such as Webpack to compile our code into browser-friendly syntax.

## Additional Resources

1. [History of JavaScript](https://auth0.com/blog/a-brief-history-of-javascript/)
2. [JavaScript version naming](https://flaviocopes.com/ecmascript/)


# 0.4.2: Common Syntax

## Learning Objectives

Understand and apply the following JS language features.

1. `let` and `const` in variable declaration
2. Block scope (ES6) vs function scope (ES5 and before)
3. Arrow functions
4. Template literals

## `let` and `const` variable declaration

In Coding Basics we may have declared variables with `var`.

```javascript
var kilometers = 10;
var randomDiceRolls = [3, 2, 4, 5];
```

In ES6 we change variable declaration syntax to use `let` and `const` instead.

```javascript
let kilometers = 10;
const randomDiceRolls = [3, 2, 4, 1];
```

The following sections are guidelines on when to use `let` vs `const`.

### `let` for primitive values that change

Use `let` if the value in our variable is a primitive data type (e.g. number, string, or boolean) and we expect the value to be reassigned.

```javascript
let kilometers = 10;
```

### `const` for primitive values that don't change

Use `const` if our variable's value will not change.

```javascript
const sidesOfDice = 6;
```

Reassigning a `const` variable throws an error.

```javascript
const pi = 3.14;
pi = 99999; // you will get an error with this line
```

### `const` for arrays and objects

We typically use `const` for arrays and objects, even if we plan to mutate the values inside them. This is because arrays and objects (and other variable-size data types over than strings) are known as ["mutable" data types](https://developer.mozilla.org/en-US/docs/Glossary/Mutable), whose variable values are actually "pointers" to "memory addresses" that store the variable-size data type. When we modify arrays and objects, the contents at their addresses may change, but the addresses and pointers themselves do not change, thus `const` is appropriate for var declarations.

```javascript
const diceRolls = [3, 4, 1, 6, 1];
```

We can alter values inside arrays declared with `const`.

```javascript
const diceRolls = [4, 2, 1, 4];
// The following affects values inside diceRolls but not the address of diceRolls
diceRolls.push(5);
```

But we cannot reassign the value of array variables declared with `const`.

```javascript
const diceRolls = [4, 2, 1, 4];
// This will cause an error for reassignment of a const variable
diceRolls = [5];
```

{% hint style="info" %}
**Comparing mutable data types**

Because variables referring to data structures store addresses, we cannot compare the values in 2 arrays with `===` because `===` will compare their memory addresses and not values. To compare values in arrays we will need to write a loop.

```javascript
// This boolean statement will return false
[1, 2, 3] === [1, 2, 3];
```

{% endhint %}

## Block scope vs function scope

Variables declared with `let` and `const` in "blocks" like an if statement will not be available outside those blocks. A block is a section of code surrounded by curly braces `{}` such as conditional statements, loops and functions. `var` in ES5 uses "function scope", which makes variables declared with `var` accessible anywhere within a given function.

#### Old Way (Function Scope)

```javascript
var myFunc = function () {
  if (diceRoll === 6) {
    var win = true;
  }
  // This will return true
  console.log(win);
};
```

#### New Way (Block Scope)

```javascript
var myFunc = function () {
  if (diceRoll === 6) {
    let win = true;
  }
  // This will error because win does not exist outside the if statement
  console.log(win);
};
```

## Arrow functions

Arrow functions are Rocket's preferred syntax for writing functions in ES6 due to their conciseness and wide adoption. There are technical considerations for when to use arrow functions vs other function declaration syntax, but none of them should matter for Rocket's Bootcamp.

### 1: Arrow function syntax

Arrow syntax is a concise syntax for initialising anonymous functions. Always use `const` when declaring a function variable (functions are a mutable data type).

```javascript
const rollDiceArrow = () => {
  var myRandomValue = Math.random();
  return myRandomValue;
};
```

{% hint style="info" %}
**Arrow functions with implicit return value**

If the right side of an arrow function is a single statement outside a block `{}`, the function will automatically return the evaluation of that statement. This allows us to write concise functions with arrow syntax.

```javascript
// Always get 5.
const rollDiceCheatArrowImplicitReturn = () => 5;

// Return result of Math.floor(Math.random() * 6 + 1)
const rollDiceArrowImplicitReturn = () => Math.floor(Math.random() * 6 + 1);
```

{% endhint %}

### 2: Regular anonymous function syntax

Like arrow function syntax except the function is declared with the `function` keyword.

```javascript
const rollDiceCheat = function () {
  // always return 6 to win.
  return 6;
};
```

### 3: Named function syntax

Explicitly name the function in the declaration after the `function` keyword.

```javascript
function rollDiceNamed() {
  var myRandomValue = Math.random();
  return myRandomValue;
}
```

## Template Literals

Rocket strongly suggests using template literals for more concise string interpolation. This will help your code be more concise and readable.

Old way: string concatenation

```javascript
let output = "you rolled " + diceRoll + ". nice job!";
```

New way: template literals

```javascript
let output = `you rolled ${diceRoll}. nice job!`;
```

## Exercises

### `let` and `const`

Open the console in Chrome DevTools. Reproduce errors from `const` examples above. What do the error messages say?

### Arrow Functions

Turn the `main` function in any code from Coding Basics (or any function in other code you've written) into an arrow function. Verify the app still works.

### Template Literals

Change string output in previous code you've written from concatenation syntax to template literal syntax. Verify the syntax works as expected.


# 0.4.3: Reference vs Value

## Learning Objectives

1. Difference between mutable and immutable data types
2. Mutable data types are passed by reference (address) and immutable data types passed by value
3. How to make an independent copy of a mutable data type

## Introduction

What will `array2.length` return in the final line?

```javascript
var array1 = [1, 2, 3];
var array2 = array1;
array1.pop(); // Remove the last element from array1
console.log(array2.length);
```

`array2.length` above returns 2. We assigned `array2` to `array1` and arrays are mutable data types, hence `array2` references the same data as `array1`. Mutable data types are passed by reference and not by value.

If we wanted to copy `array1` into an independent `array2` variable, we could run the following code instead.

```javascript
var array1 = [1, 2, 3];
// "..." syntax in front of an array is called the spread operator
// The spread operator copies all elements in an array
// The surrounding [] encapsulates copies of array1's elements into a new array
var array2 = [...array1];
array1.pop(); // Remove the last element from array1
console.log(array2.length);
```

## Mutable and Immutable Data Types in JavaScript

Mutable data types are passed by reference. To make a copy we would use the JavaScript spread operator or a loop, not direct assignment to a new variable.

Immutable data types (aka primitive values) are passed by value. To make a copy we would assign the old variable to a new one, and any changes to either variable would not affect the other.

| Data type | Immutable / Mutable |
| --------- | ------------------- |
| Boolean   | Immutable           |
| Number    | Immutable           |
| String    | Immutable           |
| Array     | Mutable             |
| Object    | Mutable             |
| Function  | Mutable             |

## Mutable and Immutable Data Types in Computer Memory

Computers store data broadly in 2 places: memory (RAM) and drive (SSD or disk). Memory is smaller, faster storage and drive is larger, slower storage. Apps run in memory and persistent data is typically stored in drive.

JavaScript references mutable data types with memory addresses because we do not know beforehand how large these data structures will be. JS can store the value of immutable data types directly without a memory address because immutable data types have a fixed size.

Consider the 2 examples at the start of this submodule. The following diagrams illustrate conceptually what happens in memory after each line of code.

Example 1:

```javascript
var array1 = [1, 2, 3];
var array2 = array1;
array1.pop();
```

![array2 references the same data structure as array1](/files/HCYHCKLopAT4SW5AxquI)

Example 2:

```javascript
var array1 = [1, 2, 3];
// "..." syntax in front of an array is called the spread operator
// The spread operator copies all elements in an array
// The surrounding [] encapsulates copies of array1's elements into a new array
var array2 = [...array1];
array1.pop();
```

![array2 references a data structure independent from array1](/files/R9VWCPI5rLJyl92OpIEC)

## Additional Resources

1. [This video](https://youtu.be/-hBJz2PPIVE) explains reference vs value with a live coding example.
2. [This video](https://youtu.be/fVVrfJM4JeY) explains in more detail how arrays are stored in memory.


# 0.4.4: Classes

## Learning Objectives

1. Understand the motivation behind JavaScript classes and object-oriented programming (OOP)
2. Understand how to use JavaScript class syntax to create and use classes
3. Understand how class inheritance works, how to use `super` to call parent class constructor

## Introduction

The following is an example of a JavaScript class that represents cars. For simplicity, these cars only travel 1 unit of distance per trip.

```javascript
class Car {
  // Define class properties in a constructor method
  constructor(colour) {
    this.colour = color;
    this.odometer = 0;
  }

  // Define class methods within the class block
  drive() {
    this.odometer += 1;
  }
}

// Create new "instances" of classes with the "new" keyword
const whiteCar = new Car("white");
const blackCar = new Car("black");

// Call class methods on instances of the class
whiteCar.drive();
blackCar.drive();
blackCar.drive();

// Retrieve class properties as we would with JS Objects
console.log(whiteCar.odometer); // 1
console.log(blackCar.odometer); // 2
```

JavaScript classes are templates for entities we may wish to manipulate as a unit in our apps. Classes are part of a broader computer science concept called object-oriented programming, also known as OOP. Classes are optional in JavaScript but mandatory in languages such as Java.

## Without classes

Without classes, we might store data in JavaScript Objects and manipulate them with helper functions.

```javascript
const whiteCar = {
  colour: "white",
  odometer: 0,
};

const blackCar = {
  colour: "black",
  odometer: 0,
};

const drive = (car) => {
  car.odometer += 1;
};
```

To reduce redundancy in object creation, we could write a helper function like `createCar` to generate our objects.

```javascript
const createCar = (colour) => {
  return {
    colour: colour,
    odometer: 0,
  };
};

const drive = (car) => {
  car.odometer += 1;
};

const whiteCar = createCar("white");
const blackCar = createCar("black");
```

## With classes

JavaScript classes encapsulate the entity properties (`colour` and `odometer` above), entity creation method (`createCar` above) and any entity helper methods (`drive` above) within a single unit, i.e. class. This helps us organise our code by thinking of a `Car` as a single entity, instead of an entity spread across disparate objects and helper functions.

```javascript
class Car {
  // Define class properties in a constructor method
  constructor(colour) {
    this.colour = color;
    this.odometer = 0;
  }

  // Define class methods within the class block
  drive() {
    this.odometer += 1;
  }
}

// Create new "instances" of classes with the "new" keyword
const whiteCar = new Car("white");
const blackCar = new Car("black");
```

We can represent many common app entities as classes, for example users.

```javascript
class User {
  constructor(name, email, password) {
    this.name = name;
    this.email = email;
    // Always only store hashed passwords to mitigate problems if data stolen
    this.passwordHash = hash(password);
  }

  changePassword(newPassword) {
    this.passwordHash = hash(newPassword);
  }
}

const joe = new User("Joe", "joe@joe.com", "joerox");
const amy = new User("Amy", "amy@amy.com", "amyrox");
```

Naming convention: Classes are typically named with UpperCamelCase. Instances are typically named with lowerCamelCase.

## Class inheritance

One of the most valuable features of OOP and classes is "inheritance". Inheritance allows classes to "inherit" properties and methods from one another by forming "parent-child" relationships. For example, if I wanted to create classes for `Bicycle` and `Car` vehicle types, both of which have a `speed` property and the same `calcTravelTime` method that depends on `speed`, I can define how we store the `speed` property and define the `calcTravelTime` method in a parent class `Vehicle` and have `Bicycle` and `Car` classes inherit from `Vehicle` to avoid repeating code.

{% code title="class-example.js" %}

```javascript
class Vehicle {
  constructor(speed) {
    this.speed = speed;
  }
  
  calcTravelTime(distance) {
    return distance / this.speed;
  }
}

/*
 * Bicycle and Car classes "inherit" properties and methods from Vehicle class
 */

class Bicycle extends Vehicle {
  constructor(speed) {
    // The super keyword runs the constructor of the parent class
    super(speed);
  }
}

class Car extends Vehicle {
  constructor(speed) {
    super(speed);
  }
}

// Declare new Bicycle and Car instances
const bicycle = new Bicycle(10);
const car = new Car (100);

// Even though we did not define calcTravelTime in Bicycle and Car, they have the method
console.log(bicycle.calcTravelTime(100)); // 
console.log(car.calcTravelTime(100));
```

{% endcode %}

1. Notice we use the keyword `extends` to specify inheritance in JavaScript
2. Notice we use the keyword `super` in constructor methods of child classes `Bicycle` and `Car` to call the constructor method of their parent, `Vehicle`.

Try creating a local file `class-example.js` with the above code and running it with `node class-example.js`, playing around with its features to understand how classes work!


# 0.4.5: Destructuring and Spread Operator

## Learning Objectives

1. What the destructuring and spread operators are and how to use them

## Introduction

ES6 Destructuring and Spread Operators provide more convenient syntax for extracting variables from and making copies of arrays and JS Objects.

## Destructuring Assignment

Assign array or object properties to new variables.

### Example: Array destructuring syntax

Assign and name variables according to their **position** in an array.

```javascript
const row = ["X", "O", "X"];
const [left, center] = row;
console.log(left); // Output 'X'
console.log(center); // Output 'O'
```

### Example: Object destructuring syntax

Assign and name variables according to their **key** in an object.

```javascript
const user = { name: "kai" };
const { name } = user; // Create a new variable called name
console.log(name); // Output 'kai'
```

### Example: Return Multiple Values from Functions

Occasionally we may need to return multiple values from a function. If we wrap those values in an object, we can use ES6 destructuring to re-initialise those values as local variables in the parent function. ES6 named imports work the same way.

```javascript
const conversions = (temperatureInFahrenheit) => {
  let temperatureInCelcius = 123; // calculation goes here
  let temperatureInKelvin = 456; // calculation goes here

  return {
    kelvin: temperatureInKelvin,
    celcius: temperatureInCelcius,
  };
};

const { kelvin, celcius } = conversions(20);
console.log(kelvin);
console.log(celcius);
```

### Example: Import Multiple Named Exports

ES6 `import` uses object destructuring to initialise variables for imported functions.

Given this file that exports 3 named functions...

{% code title="tempConversion.js" %}

```javascript
export const kilometersToMiles = (kilometers) => {
  /* ... */
};
export const celciusToFahrenheit = (temperatureCelcius) => {
  /* ... */
};
export const kilogramsToPounds = (kilograms) => {
  /* ... */
};
```

{% endcode %}

... we can import those functions using named imports in a client module.

{% code title="index.js" %}

```javascript
import {
  kilometersToMiles,
  celciusToFahrenheit,
  kilgramsToPounds,
} from "./temperatureConversion.js";

console.log(kilometersToMiles(3));
console.log(celciusToFahrenheit(3));
console.log(kilogramsToPounds(3));
```

{% endcode %}

## Spread Operator

Return a [shallow copy](https://medium.com/@manjuladube/understanding-deep-and-shallow-copy-in-javascript-13438bad941c#:~:text=Shallow%20copy%20is%20a%20bit,the%20memory%20address%20is%20copied.) of the elements or key-value pairs inside an array or object respectively.

### Example: Make Shallow Copy of Array

As we may have seen, assigning an array to a new variable creates a new reference to the original array, and does NOT make a copy of the original array.

```javascript
const temperatures = [23, 12, 45];
const temperaturesCopy = temperatures; // New var is reference to temperatures.
temperatureCopy.pop(); // This mutates the original temperatures array.
```

Spread operator syntax inside a new array declared with `[]` makes a shallow copy of the original array. The same syntax works for objects.

```javascript
const temperatures = [23, 12, 45];
const temperaturesCopy = [...temperatures]; // Make shallow copy of temperatures.
temperatureCopy.pop(); // This does NOT mutate the original temperatures array.
```

{% hint style="info" %}
**Shallow vs deep copy**

Shallow copies of arrays and objects are different from deep copies. A shallow copy is a new copy of values 1 level deep. A deep copy is a new copy of values no matter how many levels deep. Read more on shallow and deep copies in [this tutorial](https://www.javascripttutorial.net/object/3-ways-to-copy-objects-in-javascript/).
{% endhint %}

### Example: Concatenate Arrays

We can combine multiple arrays using the spread operator as below.

```javascript
const names = ["susan chan", "garfield"];
const names2 = ["alex", "chee kean"];
const combinedArray = [...names, ...names2]; // has all four elements inside
```

### Example: Concatenate Objects

Similarly, we can merge the contents of 2 objects using the spread operator as below.

```javascript
const userData = { name: "kai" };
const userData2 = { height: 6 };
const combinedUserData = { ...userData, ...userData2 }; // has both keys inside
```


# 0.4.6: Promises

## Learning Objectives

1. JavaScript Promises allow us to program logic to run after asynchronous function calls return, e.g. network requests that take an indefinite amount of time.
2. Promises are an alternative to callback functions and often a "cleaner" syntax due to fewer levels of nesting.
3. `.catch` allows us to run specified logic when our programs encounter errors in promises
4. `Promise.all` allows us to wait on multiple promises concurrently instead of sequentially

## Introduction

JavaScript Promises allow us to program logic to run after asynchronous function calls return, for example if we wanted to highlight a like button after we have saved the "like" in our database. The same logic would be possible with callback functions, but promises allow us to achieve the same functionality with at most 1 level of nesting.

The following examples use a common HTTP-request-making library called [Axios](https://axios-http.com). Axios is a promise-based HTTP library that allows us to make arbitrary HTTP requests in code. "Promise-based" means Axios functions return promises, allowing us to run certain logic only when the promises "resolve", i.e. when the requests are completed.

## `.then`

The function `axios.get` sends a GET request and returns a promise, on which we then call the promise's `.then` method to perform certain logic only when the GET request is complete, i.e. when we receive a response. 3rd-party asynchronous functions such as `axios.get` often return promises for this purpose, and when unsure we can check their [online documentation](https://axios-http.com/docs/api_intro).

The following code sends a request, then `console.log`s the response when the response is received.

```javascript
import axios from "axios";

// Make a request
axios.get("http://dog.ceo/api/breeds/image/random").then((response) => {
  // Handle request success
  console.log(response);
});
```

The previous code can be rewritten as follows for a clearer breakdown of how `.then` works.

```javascript
import axios from "axios";

// Perform logic after the request is complete.
const handleResponse = (response) => {
  // Handle request success
  console.log(response);
};

// Make a request and store return value (promise) in getRequestPromise
const getRequestPromise = axios.get("http://dog.ceo/api/breeds/image/random");

// Tell the program to call handleResponse when getRequestPromise resolves.
getRequestPromise.then(handleResponse);
```

Note that `handleResponse` receives a `response` parameter. Because the above promise is for an Axios request, the callback function receives an [Axios response object](https://axios-http.com/docs/res_schema) as a parameter.

## Sequential Promises

Sometimes we may wish to perform multiple network calls sequentially. For example, when a user requests to change their password, we may wish to:

1. Send a request to change their password
2. When that request is complete, send an email through an email API
3. Render a success message after the email is sent

```javascript
axios
  .post(`https://myapp.com/change-password`, { password: "rocket123" })
  .then((response) => axios.get(`https://myapp.com/send-email`))
  // Render password change success
  .then((response) => console.log("success!"));
```

`.then` always returns a promise, regardless of whether the callback function passed to `.then` returns nothing, a promise, or anything else. Hence we can always call `.then` on the return value of any `.then` call. See [`.then` docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then) for a more detailed description of this behaviour.

## `.catch`

`.catch` allows us to run specified logic when our programs encounter errors in promises. For example, if our above request to change password encountered an error such as invalid password or user had no account, we could program logic to return a graceful error message in the `.catch` block. Without `.catch`, our programs would crash on errors in promises.

`.catch` catches errors for all promises in the promises sequence before it. Notice there is only 1 `.catch` for the string of promises below.

```javascript
axios
  .post(`https://myapp.com/change-password`, { password: "rocket123" })
  .then((response) => axios.get(`https://myapp.com/send-email`))
  // Render password change success
  .then((response) => console.log("success!"))
  .catch((error) => {
    console.error(error);
    // Return the user a graceful error message
  });
```

## `Promise.all`

`Promise.all` allows us to wait on multiple promises concurrently instead of sequentially. For example, if I wanted to retrieve independent data to render on a page such product data and user data, I could use `Promise.all` to wait for multiple database queries to all return before proceeding. Without `Promise.all` we would need to wait for each of these queries sequentially using `.then`.

```javascript
Promise.all([
  axios.get('https://myapp.com/products/1'),
  axios.get('https://myapp.com/users/1'),
  // results is an array of results whose elements correspond
  // to the elements in the Promise.all parameter array
]).then((results) => {
  const [product1, user1] = results;
  // Do something with product1 and user1
});
```

## Additional Resources

1. [Intuitive and deeper explanation of JavaScript Promises](https://javascript.info/promise-basics)


# 0.4.6.1: Async Await

## Learning Objectives

1. Async-await can be cleaner syntax but is functionally the same as `.then` syntax
2. How to use async-await syntax to manage promise control flow in lieu of `.then`
3. Try-catch syntax provides us `.catch` functionality with async-await syntax

## Introduction

`.then` syntax:

```javascript
// myFunc returns the return value of myFunc, currently undefined
const myFunc = () => {
  axios.get("foobar.com").then((data) => {
    // Do something with data after response received
    console.log(data);
  });
};
```

Async-await syntax:

```javascript
// myFunc returns a promise due to the async keyword
// The promise resolves to the return value of myFunc
const myFunc = async () => {
  const data = await axios.get("foobar.com");
  // Do something with data after response received
  console.log(data);
};
```

Async-await syntax allows us to write asynchronous JavaScript in a synchronous manner, like in the example above. This can result in cleaner code, but does not add new functionality. Rocket does not have a strong preference whether to use async-await or `.then` syntax.

&#x20;`async` specifies a given function is asynchronous and returns a promise, and `await` will wait for a given promise to resolve before proceeding to the next line. `async` and `await` keywords must be used together; it is not meaningful to use `async` without `await`, and it is invalid to use `await` without `async`.

## Example: Async-await with `pg`

Async-await syntax is generally preferred due to its increased readability compared with `.then` syntax.

`.then` syntax:

```javascript
app.get('/users/:id', (request, response) => {
  const { id } = request.params;
  pool.query('SELECT * FROM users WHERE id = $1', [id]).then((result) => {
    const { rows } = result;
    response.send(rows);
  };
});
```

Async-await syntax:

```javascript
app.get("/users/:id", async (request, response) => {
  const { id } = request.params;
  const result = await pool.query("SELECT * FROM users WHERE id = $1", [id]);
  const { rows } = result;
  response.send(rows);
});
```

[Here](https://node-postgres.com/guides/async-express) are the official docs on how to use `pg` with async-await syntax in Express.

## Example: Catch errors with async-await

Try-catch syntax allows us to catch errors with async-await syntax in the same way we would catch errors with `.then` and `.catch` syntax.

`.then` syntax:

```javascript
const getRecipes = () => {
  // client is a Client instance from the Node pg library
  client
    // .query returns a promise
    .query("SELECT * from recipes WHERE category=vegan")
    .then((recipes) => {
      // Render the lovely vegan recipes
    })
    // The .catch block will trigger on error in either .query or .then block
    .catch((error) => {
      console.error(error);
      // Handle the error gracefully, e.g. render 404 page instead of crashing app
    });
};
```

Async-await syntax:

```javascript
const getRecipes = async () => {
  try {
    // client is a Client instance from the Node pg library
    const recipes = await client.query(
      "SELECT * from recipes WHERE category=vegan"
    );
    // Render the lovely vegan recipes
  } catch (error) {
    console.error(error);
    // Handle the error gracefully, e.g. render 404 page instead of crashing app
  }
};
```

Similar to `.catch` syntax, when there is an error in a `try` block, e.g. a request to a nonexistent URL, the error will cause our program will crash unless we catch that error in a `catch` block. Try-catch syntax is not directly related to promises, but is commonly used with async-await promise syntax.

## Example: Async-await does not pause programs, only code in current function

The following code executes "Before" and "After" `console.log`s before "Recipes".

```javascript
const getRecipes = async () => {
  try {
    // client is a Client instance from the Node pg library
    const recipes = await client.query(
      "SELECT * from recipes WHERE category=vegan"
    );
    // Render the lovely vegan recipes
    console.log("Recipes");
  } catch (error) {
    console.error(e);
    // Handle the error gracefully, e.g. render 404 page instead of crashing app
  }
};

console.log("Before");
getRecipes();
console.log("After");
```

Output

```
Before
After
Recipes
```

`getRecipes` will return before its logic has completed because it is an `async` function that contains an asynchronous `client.query`. `async` wraps `getRecipes` in a promise that returns immediately but resolves only when `getRecipes` logic is complete. Since there is no `.then` or `await` on the `getRecipes()` function call, the "After" `console.log` runs before `getRecipes` has resolved.

## Example: Async-await works with all promises, including the promise returned by `Promise.all`

We can use async-await with `Promise.all` to retrieve unrelated data concurrently with syntax that reads sequentially.

`.then` syntax:

```javascript
const getData = () => {
  const results = Promise.all([
    pool.query("SELECT * FROM recipes"),
    pool.query("SELECT * FROM categories"),
    pool.query("SELECT * FROM users"),
    // results is an array of results whose elements correspond
    // to the elements in the Promise.all parameter array
  ]).then((results) => {
    const [recipes, categories, users] = results;
    // Do something with recipes, categories and users
  });
};
```

Async-await syntax:

```javascript
const getData = async () => {
  // results is an array of results whose elements correspond
  // to the elements in the Promise.all parameter array
  const results = await Promise.all([
    pool.query("SELECT * FROM recipes"),
    pool.query("SELECT * FROM categories"),
    pool.query("SELECT * FROM users"),
  ]);
  const [recipes, categories, users] = results;
  // Do something with recipes, categories and users
};
```


# 0.5: Node.js

## Learning Objectives

1. Node.js is a JavaScript runtime that enables us to run JavaScript programs from the command line
2. Node.js provides a JavaScript development console in the command line
3. Node.js provides a `process` variable we can use to access program parameters such as command line parameters

## Introduction

Node.js (Node for short) is a JavaScript "runtime" that runs JS on our computers (as opposed to a user's browser). Node is popular because it enables SWEs to build both frontends and backends in JS, which has simplified feature development, attracted more developers to JS, and resulted in a large number of JS libraries available for both frontend and backend.

During Coding Bootcamp we will use Node for both frontend and backend applications. We will use it with Create React App on the frontend to generate static HTML, CSS and JS files for browsers through React, and we will use it with Express.js on the backend to create API servers that serve data for our apps.

## Warmup: Node console in command line

To warm up with Node, run the following command on the command line.

```bash
node
```

This should open a JS console on the command line similar to the Chrome DevTools console. We can test JS syntax in this console similar to how we might in Chrome.

```
% node
Welcome to Node.js v16.14.2.
Type ".help" for more information.
> a = [1,2,3]
[ 1, 2, 3 ]
> b = [4,5,6]
[ 4, 5, 6 ]
> a+b
'1,2,34,5,6'
> a.concat(b)
[ 1, 2, 3, 4, 5, 6 ]
```

Type `Ctrl+D` to exit, which sends an "end of file" signal to Node to close the program.

## Run JS files with Node

Node is primarily used to run JS files. Try running the following `index.js` file with Node.

{% code title="index.js" %}

```javascript
console.log("hello world");
```

{% endcode %}

```bash
node index.js
```

Over Bootcamp we will build increasingly complex programs executed with Node.

## Additional Resources

1. Introduction to runtime environments: <https://www.codecademy.com/articles/introduction-to-javascript-runtime-environments>


# 0.5.1: Node Modules

## Learning Objectives

1. Node Modules define code that can be grouped together and imported from other files
2. How to import and export functions from Node Modules
3. We can only access imported variables and variables defined in the current module
4. Understand the difference between named and default exports

## Introduction

Node Modules (aka ES Modules) define code that can be grouped together and imported from other files. This helps clarify business logic by abstracting implementation details into separate files.

Setting up the environment:

1. Create a new directory named `npm_modules`
2. Change directory to `npm_modules`
3. Run the command `npm init -y` to initialise an npm directory&#x20;
4. You should see a new file has been generated, the package.json
5. To run the scripts you will need to alter this file as below:

```
{
  "name": "npm_modules",
  "version": "1.0.0",
  "description": "modules",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
  }
}
```

Alter this file by adding in a new key and value pair.

```
{
  "type": "module",
  "name": "npm_modules",
  "version": "1.0.0",
  "description": "modules",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
  }
}
```

Now you can run your scrips with node \<scrip-name>

`operations.js` is a Node Module that exports 2 functions: `add` and `subtract`.

{% code title="operations.js" %}

```javascript
export const add = (a, b) => {
  return a + b;
};

export const subtract = (a, b) => {
  return a - b;
};
```

{% endcode %}

`index.js` imports `add` and `subtract` functions from the `operations` module and uses them.

{% code title="index.js" %}

```javascript
import { add, subtract } from "./operations.js";

console.log(add(2, 2));
console.log(subtract(2, 2));
```

{% endcode %}

`conversion.js` is a Node Module that exports functions to convert metric to US units of measurement.

{% code title="conversion.js" %}

```javascript
export const kmToMiles = (numKm) => {
  // Convert KM to miles and return value in miles
};

export const celciusToFahrenheit = (tempInCelsius) => {
  // Convert Celsius to Fahrenheit and return value in Fahrenheit
};

export const kgToPounds = (numKg) => {
  // Convert KG to pounds and return value in pounds
};
```

{% endcode %}

`index.js` imports functions from `conversion` module and uses them without having to worry about implementation details.

{% code title="index.js" %}

```javascript
import {
  kmToMiles,
  celciusToFahrenheit,
  kgToPounds,
} from "./conversion.js";

console.log(kmToMiles(3));
console.log(celciusToFahrenheit(3));
console.log(kgToPounds(3));
```

{% endcode %}

## Module Scope

Node Modules can only access variables explicitly imported or defined in their file. For example, the variable `PI` in the following `circleUtils` module is not accessible in `index.js` because `PI` is not explicitly imported or defined in `index.js`.

{% code title="circleUtils.js" %}

```javascript
const PI = 3.14;

export const getCircleArea = (r) => {
  return PI * (r * r);
};

export const getCirclePerimeter = (r) => {
  return 2 * PI * r;
};
```

{% endcode %}

{% code title="index.js" %}

```javascript
import { getCircleArea } from "./circleUtils.js";

// PI is used "inside" this function
console.log(getCircleArea(2));
// But PI is not accessible as a variable unless explicitly exported and imported
console.log(PI); // Error
```

{% endcode %}

## Named vs Default Exports

There are 2 ways of exporting variables from Node Modules: named and default.

### Named Exports

Named exports allow us to export 0 or more named variables from modules. This is helpful when we want to export more than 1 function from a module.

In the `circleUtils` module, we export `getCircleArea` and `getCirclePerimeter` but not `PI`.

{% code title="circleUtils.js" %}

```javascript
const PI = 3.14;

export const getCircleArea = (r) => {
  return PI * (r * r);
};

export const getCirclePerimeter = (r) => {
  return 2 * PI * r;
};
```

{% endcode %}

In `index.js` we can choose which named exports to import. In this case we only import `getCircleArea`, but we could also import `getCirclePerimeter` if we wanted.

{% code title="index.js" %}

```javascript
import { getCircleArea } from "./circleUtils.js";

console.log(getCircleArea(2));
```

{% endcode %}

### Default Exports

Use default exports when the module only does 1 operation, and all functions in that module exist to support that operation. In general we prefer named exports for clarity of what is exported and imported. Each module can only have 1 default export.

In the `calcHandScore` module, the only function that needs access externally is `calcHandScore`, which we export as a default export.

{% code title="calcHandScore.js" %}

```javascript
const checkFullHouse = (hand) => {
  // Verify if card hand has a full house
};

const checkStraight = (hand) => {
  // Verify if card hand has a straight
};

const calcHandScore = (hand) => {
  let handScore = 0;
  if (checkFullHouse(hand)) {
    // Update handScore for full house
  } else if (checkStraight(hand)) {
    // Update hand score for straight
  }
  return handScore;
};

export default calcHandScore;
```

{% endcode %}

`index.js` imports the `calcHandScore` function, allowing it to calculate the score of a card hand without having to worry about the implementation details of how to calculate it.

Note we do not use curly braces `{}` when importing default exports.

{% code title="index.js" %}

```javascript
// No curly braces around imported default export
import calcHandScore from "./calcHandScore.js";

const hand = ["A", "A", "A", "K", "K"];
const handScore = calcHandScore(hand);
console.log(handScore);
```

{% endcode %}

## Additional Resources

1. [Summary of Node Module usage in 100 seconds](https://youtu.be/qgRUr-YUk1Q)


# 0.5.2: NPM

## Learning Objectives

1. NPM is a package manager that allows us to install and use 3rd-party Node libraries in our apps
2. Know how to install packages in an NPM project
3. Know what role the files `package.json`, `package-lock.json`, and the folder `node_modules` play with NPM

## Introduction

![NPM allows us to install, manage and use 3rd-party packages](/files/tx1QtNHACpEIkq3uPCyR)

[NPM](https://www.npmjs.com) (Node Package Manager) is Node's most popular package manager and allows us to install 3rd-party software packages (aka libraries) in our apps. All apps use 3rd-party libraries, and package managers like NPM simplify managing app dependencies.

## Follow Along

We recommend you initialise your own NPM project to inspect the files we discuss on this page.

To create a new NPM project, create a folder, `cd` inside and initialise a new NPM project in that folder with `npm init -y`. The `-y` flag accepts defaults by answering `yes` to all setup questions.

```
mkdir my-first-npm-project
cd my-first-npm-project
npm init -y
```

## `package.json`

If we created our NPM project as above, we should now see a single file in `my-first-npm-project`: `package.json`.

```
% mkdir my-first-npm-project
% cd my-first-npm-project
my-first-npm-project % npm init -y
Wrote to /Users/kai/rocket-code/my-first-npm-project/package.json:

{
  "name": "my-first-npm-project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}


my-first-npm-project % ls
package.json
```

`package.json` is the most important file in an NPM project because it specifies which packages our project depends on. When we install new packages, `package.json` lists those packages' names and versions. When other SWEs clone our code on their own computers and need to run it, `package.json` helps them install the exact packages and versions they need.

The following is the `package.json` generated after running `npm init -y`. Notice it has no packages yet, but contains other metadata for our project that is less relevant for us now.

{% code title="package.json" %}

```json
{
  "name": "my-first-npm-project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}
```

{% endcode %}

## Installing NPM Packages

To install NPM packages, run the install command `npm install`, or `npm i` for short, followed by the package name. The following command downloads and installs the [`cows` package](https://www.npmjs.com/package/cows), a package to create ASCII cow images.

{% code title="Command" %}

```
npm i cows
```

{% endcode %}

{% code title="Sample Output" %}

```
my-first-npm-project % npm i cows

added 1 package, and audited 2 packages in 3s

found 0 vulnerabilities
```

{% endcode %}

After installing `cows`, we should see 1 new file and 1 new folder: `package-lock.json` and `node_modules` respectively in addition to `package.json`.

```
my-first-npm-project % ls
node_modules		package-lock.json	package.json
```

Feel free to peek at `package-lock.json` and `node_modules`, but their contents are primarily metadata for our app that we most likely never need to touch. `package-lock.json` lists the versions of the packages we installed and of the packages that our installed packages depend on, aka "dependencies". `node_modules` contains code of installed packages and their dependencies. NPM relies on all 3 of these files and folders to operate.

`package.json` should now look like the following.

{% code title="package.json" %}

```json
my-first-npm-project % cat package.json
{
  "name": "my-first-npm-project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "cows": "^2.1.1"
  }
}
```

{% endcode %}

Notice there is a new `dependencies` section that contains the package `cows` and its version. Now, any time we clone a copy of this project and run `npm i` from within the project folder, NPM will install the packages listed in this `dependencies` section of `package.json`.

## Using NPM Packages

Popular NPM packages almost always have clear instructions on how to use the package. We can typically find these instructions on the [NPM website](https://www.npmjs.com/package/cows) and on the [package's GitHub repo](https://github.com/sindresorhus/cows).

{% hint style="info" %}
**Require vs Import Syntax**

You may notice the `cows` package instructions tell us to import `cows` with `require`. This is an older version of JS syntax still widely seen but being phased out.

{% code title="Require Syntax" %}

```javascript
const cows = require("cows");
```

{% endcode %}

The above `require` statement can be translated to the below `import` statement. `require` statements translated to `import` always use default exports, because there are no named exports with `require` syntax.

{% code title="Import Syntax" %}

```javascript
import cows from "cows";
```

{% endcode %}

`import` statements work out of the box in Create React App, but to use them with NPM we will need to add `"type": "module"` key value pair to `package.json`.
{% endhint %}

When you are trying to implement the Cows package it will be very helpful if you visit the [documentation](https://github.com/sindresorhus/cows) so you know the conventional usage of this package.&#x20;

First you will need to import (or require) the package and then invoke the cows() function to output the ASCII Cows. You may need to console.log the output of the function.&#x20;

## What to Commit to Git

We should always commit both `package.json` and `package-lock.json` to Git for others that clone our project to have the same packages and versions.

We should avoid committing `node_modules` to Git, because `node_modules` can get large, and everything in `node_modules` can be installed with `npm i`. Committing large files like `node_modules` to Git can unnecessarily slow down Git operations such as pulling and pushing from GitHub.

{% hint style="info" %}
**Automatically ignore specified files and folders in Git**

Git allows for a special file called `.gitignore` anywhere in a Git repo that instructs Git to ignore specified files. To always ignore folders like `node_modules`, we can add `node_modules` on a line of its own in a `.gitignore` file in the NPM project's root directory.
{% endhint %}

## How to Find NPM Packages

NPM packages are typically discovered via Google Search and tutorials. During Rocket's Bootcamp we will direct you to all packages we need, although Rocket encourages you to independently find new packages to enhance your projects, especially for your capstone.


# 0.5.3: Nodemon

## Learning Objectives

1. Nodemon auto-refreshes Node applications on code changes, helpful for development

## Introduction

[Nodemon](https://www.npmjs.com/package/nodemon) is an application that restarts our Node app every time we change a file that the app depends on. This is especially useful in development when we make frequent changes to our code. Without Nodemon we would need to manually quit and restart our app on code changes.

## Usage

1. Install Nodemon globally to run Nodemon from all folders.

   ```
   npm i -g nodemon
   ```
2. Run `nodemon` on the entry file of our app. When any app files changes, Nodemon will restart the app.

   ```
   nodemon index.js
   ```


# 1: Frontend

## Learning Objectives

1. Learn how to build web pages and applications with HTML, CSS and React
2. Learn how to use and architect React Components, Props and State
3. Learn how to customise UI with CSS
4. Learn how to use React UI frameworks such as React Bootstrap and Material UI

## Introduction

Welcome to frontend engineering. We will develop modern frontend web applications using HTML, CSS, JS and React. All web applications are built with HTML, CSS and JS, and React has been the most popular web framework for past years. Despite building web applications, concepts we will learn such as components, state and layout will also apply to mobile and desktop applications. Module 1 culminates in Project 1, where we will build an app of our choice using these frontend technologies.


# 1.1: HTML

## Learning Objectives

1. HTML is a set of tags that defines elements on all web pages
2. Understand basic HTML document structure
3. Understand how to use common tags

## Introduction

```markup
<!DOCTYPE html>
<html>
  <head>
    <title>My First Page</title>
  </head>
  <body>
    <h1>My First Header</h1>
    <p>My first paragraph</p>
  </body>
</html>
```

HTML (HyperText Markup Language) defines elements on web pages. All web pages, even the most complex ones rely on HTML to represent their elements. In upcoming modules we will learn how to use CSS and JS to apply styling and interactivity to HTML elements.

HTML comprises tags and content between them. Web browsers read HTML and render content between tags based on tag specifications. For example, browsers will render content between "Header 1" (`h1`) opening (`<h1>`) and closing (`</h1>`) tags as large headers, and content between opening and closing "Paragraph" tags (`p`) in paragraph format.&#x20;

```html
<h1>My First Heading</h1>
<p>My first paragraph.</p>
```

## Basic HTML Structure

All HTML documents generally start with the following declaration to use the latest version of HTML.

```html
<!DOCTYPE html>
```

After the `DOCTYPE` declaration is typically a set of `html` opening and closing tags surrounding all page content.

```html
<!DOCTYPE html>
<html>
  Page content
</html>
```

The first set of tags within the outermost `html` tags is usually the `head` tags. `head` tags contain important site metadata such as title (what's displayed in the browser tab bar), SEO metadata and links to stylesheets for styling and JavaScript for interactivity.

```html
<!DOCTYPE html>
<html>
  <head>
    <title>My First Page</title>
  </head>
</html>
```

`body` tags typically follow `head` tags. `body` tags contain the content of the page. The following example includes `body` tags with `h1` and `p` tags within them, specifying content to render on the page.

```html
<!DOCTYPE html>
<html>
  <head>
    <title>My First Page</title>
  </head>
  <body>
    <h1>My First Header</h1>
    <p>My first paragraph</p>
  </body>
</html>
```

That is the basic structure of all HTML pages. Feel free to play around with live examples on [W3Schools](https://www.w3schools.com/html/html_examples.asp).

## Common HTML Tags

### Summary

The following are common HTML tags we are most likely to use and encounter. Block elements occupy full page width and inline elements only occupy width of their content.

| Tag name              | Description                                             | Block vs inline |
| --------------------- | ------------------------------------------------------- | --------------- |
| `div`                 | Divider tag. Serves as group for other tags.            | Block           |
| `span`                | Span tag. Apply styles to inline content.               | Inline          |
| `h1`, `h2`, ..., `h6` | Header tags. `h1` is largest and `h6` is smallest.      | Block           |
| `p`                   | Paragraph tag. Used to separate paragraphs of text.     | Block           |
| `strong`, `em`        | Bold and italicise tags.                                | Inline          |
| `a`                   | Anchor tag. Link to another page with a URL.            | Inline          |
| `img`                 | Image tag. Render an image.                             | Inline          |
| `ol`, `ul`, `li`      | Ordered list, unordered list, list item. Render a list. | Block           |
| `table`, `tr`, `td`   | Table, table row, table data. Render a table.           | Block           |

### Anchor Tags (`a`)

Anchor tags link to other webpages and require an `href` parameter that contains a URL.&#x20;

```html
<a href="rocketacademy.co">Best Coding Bootcamp</a>
```

To make the link open in a new tab, include the parameter `target="_blank"`.

```markup
<a href="rocketacademy.co" target="_blank">Best Coding Bootcamp</a>
```

### Image Tags (`img`)

Image tags are self-closing and do not have separate opening and closing tags. They require `src` and `alt` parameters representing the source of the image and alternate text describing the image for accessibility, SEO and to display if the image is not available. `src` can be either a file path or a URL.

```html
<img src="images/rocketrocks.png" alt="Rocket rocks!" />
```

We can wrap tags in each other to combine their functionality. For example, we can make an image a link by wrapping an `img` tag with an `a` tag.

```markup
<a href="rocketacademy.co" target="_blank">
  <img src="images/rocketrocks.png" alt="Rocket rocks!" />
</a>
```

### List Tags (`ol`, `ul`, `li`)

Wrap lists with `ol` (ordered) or `ul` (unordered) and wrap each list item with `li`.

{% code title="Ordered List" %}

```html
<ol>
  <li>Study</li>
  <li>Practise</li>
  <li>Success</li>
</ol>
```

{% endcode %}

{% code title="Unordered List" %}

```html
<ul>
  <li>Great students</li>
  <li>Great teachers</li>
  <li>Great school</li>
</ul>
```

{% endcode %}

### Table Tags (`table`, `tr`, `th`, `td`)

Wrap tables with `table`, table rows with `tr`, table headers in the 1st row with `th` and table data in subsequent rows with `td`.

```markup
<table>
  <tr>
    <th>Company</th>
    <th>Contact</th>
    <th>Country</th>
  </tr>
  <tr>
    <td>Alfreds Futterkiste</td>
    <td>Maria Anders</td>
    <td>Germany</td>
  </tr>
  <tr>
    <td>Centro comercial Moctezuma</td>
    <td>Francisco Chang</td>
    <td>Mexico</td>
  </tr>
</table>
```

### Basic HTML Document&#x20;

<pre class="language-html"><code class="lang-html">&#x3C;!DOCTYPE html>
&#x3C;html>
  &#x3C;head>
    &#x3C;title>Rocket Academy&#x3C;/title>
  &#x3C;/head>
  &#x3C;body>
    &#x3C;h1>Welcome to Coding Bootcamp!&#x3C;/h1>
    &#x3C;a href="rocketacademy.co" target="_blank">
      &#x3C;img src="images/rocketrocks.png" alt="Rocket rocks!" />
    &#x3C;/a>
    &#x3C;ol>
      &#x3C;li>Study&#x3C;/li>
      &#x3C;li>Practise&#x3C;/li>
      &#x3C;li>Success&#x3C;/li>
    &#x3C;/ol>
    &#x3C;h2>What are we going to learn? &#x3C;/h2>
    &#x3C;table>
      &#x3C;tr>
        &#x3C;th>Topic&#x3C;/th>
        &#x3C;th>Module&#x3C;/th>
        &#x3C;th>Difficulty&#x3C;/th>
      &#x3C;/tr>
      &#x3C;tr>
        &#x3C;td>React&#x3C;/td>
        &#x3C;td>One&#x3C;/td>
        &#x3C;td>Easy&#x3C;/td>
      &#x3C;/tr>
      &#x3C;tr>
        &#x3C;td>Firebase&#x3C;/td>
        &#x3C;td>Two&#x3C;/td>
        &#x3C;td>Intermediate&#x3C;/td>
<strong>      &#x3C;/tr>
</strong>      &#x3C;tr>
        &#x3C;td>ExpressJs&#x3C;/td>
        &#x3C;td>Three&#x3C;/td>
        &#x3C;td>Advanced&#x3C;/td>
      &#x3C;/tr>
    &#x3C;/table>
  &#x3C;/body>
&#x3C;/html>
</code></pre>

Notice how this html document is composed of a single `html` tag, which contains the `head` and `body` tags. The as stated above, the head tag contains the required meta data for SEO, but it also provides the browser with key information concerning what it should display. Above we have used a title tag such that the tab in the browser would read 'Rocket Academy'. With this in mind the `head` allows us to insert stylesheets which would inform the browser of how to display and render out html content. In the next section will cover how you can style and how you amend the `head` tag to link required CSS. &#x20;

Note that there is also only one body tag, this is where all of the html markup should be placed. Think of html as the structure of your website, developers use html elements to render information onto the browser, choosing the specific tag for the information type.&#x20;


# 1.2: CSS

## Learning Objectives

1. CSS enables us to style HTML pages by applying styles and layout properties on HTML elements
2. Know how to apply CSS styles to HTML elements via type, class and ID selectors
3. Understand the concept of CSS specificity

## Introduction

CSS (Cascading Style Sheets) enables styling of HTML pages by applying styles and layout properties on HTML elements. CSS styles customise size, borders, font, background, opacity, position and more.

The following CSS rule applies `text-align` and `color` properties to all HTML `p` tags.

```css
p {
  text-align: center;
  color: red;
}
```

## CSS Rules

CSS consists of **rules** like the example above, where rules consist of **selectors** (`p` tag above) and **declarations** (`text-align` and `color` declarations above).

CSS "selectors" can be HTML tags, CSS "classes", CSS "IDs", or any combination of tags, classes and IDs. CSS classes and IDs are typically kebab-case strings that we label HTML elements with to apply styles to those elements with CSS. Classes are reusable across multiple elements; IDs are meant for only 1 element. Class selectors are prefixed with `.` and ID selectors are prefixed with `#`. When developing applications, it is imperative that one utilises CSS "classes" to preserve style that is consistent across multiple pages or elements, this makes maintenance and alterations of these commonly styled elements straightforward and easy.&#x20;

```css
.my-class {
  color: red;
}

#my-id {
  color: green;
}

.my-class #my-id {
  color: blue;
}
```

We can tag HTML elements with classes and IDs by adding `class` and `id` attributes to HTML tags like in the following example.

```markup
<p class="my-class" id="my-id">I have both a class and an ID!</p>
```

CSS "declarations" tell our browsers what styles to apply to HTML elements that match the CSS rule's selector. Declarations consist of a **property** and a **value**.

```css
selector {
  property: value;
}
```

## Common CSS properties

If you would like to explore the endless styling and presentation possibilities that CSS offers please have a [look here](https://www.w3schools.com/css/). Otherwise here are some common CSS properties that you should become aware of.

| CSS property     | Description                                                                                                                                                                                                                                   | Example usage                                                                |
| ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
| color            | Set the text `color` using predefined colour names, or RGB, HEX, HSL, RGBA, HSLA values.                                                                                                                                                      | <p></p><p>p {<br>    color: #ffffff;<br>}</p>                                |
| background-color | Set the `background-color` using predefined colour names, or RGB, HEX, HSL, RGBA, HSLA values.                                                                                                                                                | <p>div {<br>    background-color : #fff;<br>}</p>                            |
| border           | The `border` property allows you to set the width, style and colour of the border. There are various styles border which are affected by colour and width. It is possible to set each of these properties individually.                       | <p>div { </p><p>    border: 2px solid #000;</p><p>}</p>                      |
| font-size        | Set the `font-size` property, this sets the size of the text. It is possible to apply relative or absolute size when setting this property.                                                                                                   | <p>p {<br>    font-size: 12px;<br>}</p>                                      |
| margin           | Set the space around the element, this is outside of any defined borders. You can define `margin` using shorthand or targeting individual sides. In the example we are using shorthand to define the top, right, bottom and then left margin  | <p>div { </p><p>    margin: 10px 15px 10px                15px;</p><p>}</p>  |
| padding          | Set the space inside the element, this is inside of any defined borders. You can define `padding` using shorthand or targeting individual sides. In the example we are using shorthand to define the top, right, bottom and then left padding | <p>div { </p><p>    padding: 10px 15px 10px                15px;</p><p>}</p> |
| height           | Set the `height` of the element. Commonly this is set with `length`, `%` or `inherit`. But there is more.  Note that this does not include margins, borders or padding.                                                                       | <p>div { </p><p>    height: 50%;</p><p>}</p>                                 |
| width            | Set the `width` of the element. Commonly this is set with `length`, `%` or `inherit`. Note that this does not include margins, borders or padding.                                                                                            | <p>div { </p><p>    width: 200px;</p><p>}</p>                                |
| overflow         | The `overflow` property informs the browser whether it should add scrollbars or clip the content when its too larger to fit in its specified area.                                                                                            | <p>div {<br>    overflow: scroll;<br>}</p>                                   |

## Using CSS classes&#x20;

When styling our HTML elements it is possible to apply multiple class names to the element, to do so just add the whatever class names within the class property separated by a space. Note that the last class takes precedence in terms of applied style.&#x20;

```html
    <p class="bordered centered red">Style me!</p>
```

## CSS Specificity

The word "cascading" in CSS refers to the hierarchy that CSS uses to apply styles to HTML elements, also known as "**specificity**". To illustrate specificity we will share 3 examples.

### Example 1: Selector hierarchy

Generally, styles applied to ID selectors take precedence over styles applied to class selectors, which take precedence over styles applied to HTML tag selectors (aka type selectors).

In the following example, the 1st paragraph will have colour red, the 2nd green, the 3rd blue. This is because styles applied to CSS IDs take precedence over styles applied to CSS classes, which take precedence over styles applied to HTML tags.

```html
<!DOCTYPE html>
<html>
  <head>
    <style>
      p {
        color: red;
      }
      .para-class {
        color: green;
      }
      #para-id {
        color: blue;
      }
    </style>
  </head>
  <body>
    <p>Every paragraph will be affected by the style.</p>
    <p class="para-class">Me too!</p>
    <p class="para-class" id="para-id">And me!</p>
  </body>
</html>
```

### Example 2: Directness hierarchy

Regardless of selector type (ID, class or type selector), CSS rules that apply more directly to selected HTML elements will take precedence over CSS rules less directly applied. For example, if I apply a CSS rule with an ID selector on a parent HTML element and a CSS rule with a type selector on the child, the type selector's declarations will override the ID selector's.

In the following example, the paragraph text will be red even though its parent element's CSS rule specifies the colour blue. This is because the `p` selector applies more directly to the `p` tag than the `div-id` selector.

```html
<!DOCTYPE html>
<html>
  <head>
    <style>
      p {
        color: red;
      }
      #div-id {
        color: blue;
      }
    </style>
  </head>
  <body>
    <div id="div-id">
      <p>Roses are red</p>
    </div>
  </body>
</html>
```

### Example 3: Style location hierarchy

CSS rules declared inline (aka "inline" styles) take precedence over CSS rules declared within `style` tags in the same file (aka "internal" styles), which take precedence over CSS rules declared in separate files (aka "external" styles).

Inline styles can be convenient for testing styles in development but are troublesome to maintain because it becomes difficult to keep track of which styles are declared where.

{% code title="Inline styles" %}

```html
<p style="color: red;">This text is red</p>
```

{% endcode %}

Internal styles allow us to centralise styles for a given HTML file in `head`. Not often used because internal styles cannot be re-used across HTML files.

{% code title="Internal styles" %}

```html
<html>
  <head>
    <style>
      p {
        color: green;
      }
    </style>
  </head>
  <body>
    <p>This text is green</p>
  </body>
</html>
```

{% endcode %}

External styles are styles declared in CSS-specific files and "imported" with `link` tags in relevant HTML files. Most apps use external styles to re-use CSS styles across multiple HTML files.

{% code title="External styles" %}

```html
<html>
  <head>
    <link rel="“stylesheet”" href="styles.css" />
  </head>
  <body>
    <p>This text is blue</p>
  </body>
</html>
```

{% endcode %}

{% code title="styles.css" %}

```css
p {
  color: blue;
}
```

{% endcode %}

Unless we have a strong reason not to, Rocket recommends using external styles for all CSS to keep our CSS rules centralised in CSS files that can be re-used across HTML files.

Unless we plan to be CSS specialists, we do not need to memorise exact CSS specificity of every permutation of selectors and HTML elements. Most browsers provide precise tools to debug CSS specificity, and [W3Schools documents](https://www.w3schools.com/css/css_specificity.asp) how to calculate CSS specificity when we need to.

## Exercises

### Apply CSS to HTML

Apply CSS to an HTML file. Create an `index.html` file with the contents below and open it in Chrome.

{% code title="index.html" %}

```html
<html>
  <head>
    <title>My HTML Page</title>
  </head>
  <body>
    <h1>I will be styled</h1>
  </body>
</html>
```

{% endcode %}

Notice what the un-styled HTML looks like. Now insert the following `style` HTML element within the `head` tags in `index.html`.

```html
<style>
  h1 {
    background-color: blue;
    color: white;
  }
</style>
```

Refresh `index.html` in Chrome and observe the change to the `h1` element.

### Codecademy Learn CSS

Complete all exercises in the following Codecademy lessons when they are assigned in the Rocket course schedule. You will need to register a Codecademy account if you have not already.

1. [Setup and Syntax](https://www.codecademy.com/courses/learn-css/lessons/learn-css-setup-and-syntax/exercises/intro-to-css)
2. [Selectors](https://www.codecademy.com/courses/learn-css/lessons/learn-css-selectors/exercises/type)
3. [Visual Rules](https://www.codecademy.com/courses/learn-css/lessons/css-visual-rules/exercises/font-family)
4. [The Box Model](https://www.codecademy.com/courses/learn-css/lessons/box-model-intro/exercises/box-model)
5. [Changing the Box Model](https://www.codecademy.com/courses/learn-css/lessons/box-model-new/exercises/box-content)


# 1.2.1: Layout

## Learning Objectives

1. CSS layout is about organising HTML elements into nested boxes and determining their positions
2. CSS box model determines the size of each element on screen
3. CSS `display` property controls the manner in which elements appear on screen, e.g. in horizontal or vertical order
4. CSS `position` property allows us to position elements outside of the normal document flow, e.g. a fixed navbar or chat window
5. Flexbox allows simple and robust layout of collections of HTML elements

## Introduction

![Organise HTML elements into conceptual boxes before planning how to use CSS for layout. Source: W3Schools](/files/HgvSt0kfPkLaGUtNxUbL)

When determining how to layout elements with CSS, first organise elements into nested boxes, then determine which CSS styles need to apply to which boxes. By default browsers will render all HTML elements in a single vertical column.

## CSS Box Model

![Margin is spacing outside the content's border. Padding is spacing inside the content's border. Source: W3Schools](/files/CRKIwbyptBApgyzIVTzx)

​

The CSS box model controls how much space an element takes on screen with CSS properties such as content `width`, content `height`, `margin` (area outside border), `border` (area surrounding content) and `padding` (area inside border but outside content). While helpful for controlling exact size of HTML elements, we recommend using flexbox properties (covered in later submodule) to layout HTML elements for a more robust layout.

### 3 common ways to specify box dimensions

**1) Pixel count**

Only works for block display elements. Generally less recommended because difficult to create responsive (mobile and desktop-friendly) layouts with fixed pixel sizes.

```css
p {
  width: 100px;
  height: 100px;
}
```

**2) Percent of parent container**

Percentage is relative to the parent container, allows responsive sizing. Percentage height does not work unless parent has fixed size.

```css
p {
  width: 50%;
  height: 100px;
}
```

**3) Percent of viewport (window)**

Viewport sizing allows for most responsive sizing based on screen size, but needs to be coordinated with other elements on screen since sizing is not relative to other elements.

```css
p {
  width: 100vw;
  height: 100vh;
}
```

[W3Schools documents](https://www.w3schools.com/cssref/css_units.asp) all ways to specify box size.

### Debugging CSS boxes

Chrome helps us visualise CSS box properties of every element on every page at the bottom of the Styles window in the Elements tab in Chrome DevTools. To see box properties of any HTML element, right click the element and click "Inspect". Box properties in the box visualisation should match the most-specific box properties at the top of the CSS styles list (ordered in decreasing specificity).

![Chrome DevTools helps us visualise box properties of every HTML element on screen](/files/UxkIrJjXrFUNAkAHNk01)

{% hint style="info" %}
**Apply `box-sizing` CSS property to include padding and border in box size**

CSS does not include padding and border in box size by default. In the following example, CSS produces a box 300px wide (including 50px of padding on both sides), even though we specify width of 200px.

```css
p {
  width: 200px;
  padding: 50px;
}
```

To make `width` and `height` include padding and border space, apply the `box-sizing` CSS property to all elements.

```css
* {
  box-sizing: border-box;
}
```

[More on `box-sizing` by W3Schools](https://www.w3schools.com/css/css3_box-sizing.asp).
{% endhint %}

## CSS `display` Property

The CSS `display` property controls the way target elements render on screen. The 2 most basic `display` values are `block` (full screen width) and `inline` (width of element only). By default, every HTML element has either block or inline layout.

`inline-block` is a 3rd `display` property that enables `inline` elements with `block` properties such as spacing on all sides. `inline` elements cannot have custom spacing around them.

![block, inline and inline-block are the most basic CSS display values. Source: Stack Overflow](/files/iA6RjN2y8gQkl6S3nmdn)

### Centring elements on screen

The `margin` property's `auto` value allows us to automatically set left and right margins to centre an element on screen. `inline` elements cannot be centred because `inline` elements cannot have `margin` settings.

```css
.main {
  margin: 0 auto; /* 0 top and bottom margin, auto left and right margin */
}
```

### Constraining element width

We may also want to constraint element width to prevent content from becoming hard to read across the full width of a horizontal screen. We will look at fixed, percent and max width layout to do this. Width settings do not apply to `inline` elements.

**Fixed-Width Layout**

Fixed-width layout fixes the width of the target element, regardless of how small or large the screen size is. This works for large screen sizes but may look poor on small screen sizes.

```css
.main {
  width: 600px; /* 600px is reasonable default width of centre column */
  margin: 0 auto; /* 0 top and bottom margin, auto left and right margin */
}
```

**Percent-Width Layout**

Percent-width layout fixes width to be a percentage of screen width. This makes our content responsive but may not be what we want, especially if we want layout to be different across mobile and desktop.

```css
.main {
  width: 80%;
  margin: 0 auto; /* 0 top and bottom margin, auto left and right margin */
}
```

**Max-Width Layout**

Max-width layout allows our element to occupy 100% of screen width at smaller screen sizes but only a specified width at larger screen sizes. This helps when we wish to maximise screen real estate on mobile devices but not make content too wide on desktop devices.

```css
.main {
  max-width: 600px; /* be 100% width, until 600px */
  margin: 0 auto; /* 0 top and bottom margin, auto left and right margin */
}
```

## CSS `position` Property

The CSS `position` property allows us to position HTML elements outside the normal "flow" of an HTML document. We can use `position: fixed` to fix a navbar to the top of a screen even when we scroll down; We can use `position: absolute` to position a counter at the top right corner of a notification icon.&#x20;

### Position Offset Properties

Position offset properties `top`, `right`, `bottom`, `left` set the relevant offset from the element's position. We can use any [CSS unit](https://www.w3schools.com/cssref/css_units.asp) to express offset.

```css
p {
  top: 300px; /* Offset p elements by 300px from the top of where they would be */
}
```

### `position` Property Values

There are 5 `position` property values: `static`, `relative`, `fixed`, `absolute` and `sticky`. `static` is the default property for all elements with no explicit `position` value. `relative` is relative to where the element would have otherwise been. `fixed` is a fixed position on screen regardless of where the user scrolls. `absolute` is relative to the closest explicitly-positioned ancestor element. `sticky` is a combination of relative and fixed. Read more about each value and how to use them at [W3Schools](https://www.w3schools.com/css/css_positioning.asp).

{% hint style="info" %}
**`z-index`**

When playing with `position` values its possible we will have elements in front of and behind each other on screen. By default the overlapping element mentioned last in the HTML document will be in front. To alter elements' relative forward and backward positions on screen, use the [CSS `z-index` property](https://www.w3schools.com/css/css_z-index.asp).&#x20;
{% endhint %}

## Flexbox

Flexbox allows simple and robust layout of collections of HTML elements. Without specifying specific distances or percentages, flexbox allows us to position elements in vertical or horizontal order, at the start, middle or end of their container, grouped together or spaced evenly apart, with or without specific ratios between elements.

To use flexbox we need to set "flex properties" on both containers of the elements we wish to position and and the elements themselves. The containers are known as "flex containers" and the elements they contain are known as "flex items".

There are some common flex patterns that we should become aware of as developers as well as some key flex properties that should be explored before to applying flex onto our websites. Generally the properties `flex`, `flexDirection`, `alignItems` and `justifyContent` are utilised to achieve the desired layout. &#x20;

Say we had this CSS classes and code block:

```html
<div>
   <div class="circle"></div>
   <div class="circle"></div> 
   <div class="circle"></div>
   <div class="circle"></div>
</div>
```

```css
.circle {
  border-radius: 100%;
  height: 100px;
  width: 100px;
  border: 2px solid #000000;
  margin: 10px;
}
```

The resulting output on the screen would look something like this:

<figure><img src="/files/fuLJMx2D9j9LwlSmBR3v" alt=""><figcaption><p>Example without flex</p></figcaption></figure>

Lets add a flex property on the div containing all of the circle elements.

```html
<div class="flexContainer">
   <div class="circle"></div>
   <div class="circle"></div> 
   <div class="circle"></div>
   <div class="circle"></div>
</div>
```

```css
.circle {
  border-radius: 100%;
  height: 100px;
  width: 100px;
  border: 2px solid #000000;
  margin: 10px;
}
.flexContainer {
  display: flex;
}
```

By adding the class `flexContainer` to the parent element and applying the `display: flex;` property,  we take each "flex item" and alter how they are rendered onto the screen. In this case we stop them from appearing as block level elements and make them appear as in-line elements.  The elements now appear like this:

<figure><img src="/files/meHfl1RXyeBfxtPyTpXh" alt=""><figcaption><p>Example with just flex</p></figcaption></figure>

The next flex property that we will explore is `flexDirection`, this specifies to the direction the container should stack the "flex items", as a `column` or `row`, you can even alter the order of the "flex items"  with the `row-reverse` or `column-reverse` value. Below we alter the last element in the container to appear as a sqaure, but we will alter the elements order and make it a column again.&#x20;

```html
<div class="flexContainer">
   <div class="circle"></div>
   <div class="circle"></div> 
   <div class="circle"></div>
   <div class="circle square"></div>
</div>
```

```css
.circle {
  border-radius: 100%;
  height: 100px;
  width: 100px;
  border: 2px solid #000000;
  margin: 10px;
}

.square {
  border-radius: 0%;
}

.flexContainer {
  display: flex;
  flex-direction: column-reverse;
}
```

<figure><img src="/files/eBZSqLSIL63UP5vg7GKW" alt=""><figcaption><p>flex and flex direction</p></figcaption></figure>

Altering the order and changing the direction though important isn't really what developers use flex for. Flex allows developers to state how they want information rendered, depending on the size of the screen, the number of items and size of the items flex will dynamically sort out each element to render it on screen. In the next example we will explore `flex-wrap` which can wrap the "flex-items" if they overflow out of their current container. Below is the code were we apply `flex-wrap` and add in additional elements. When applying this property you can use `wrap`, `no-wrap` and `wrap-reverse`.

```html
<div class="flexContainer">
   <div class="circle"></div>
   <div class="circle"></div> 
   <div class="circle"></div>
   <div class="circle"></div>
   <div class="circle"></div> 
   <div class="circle"></div>
   <div class="circle"></div>
   <div class="circle"></div> 
   <div class="circle"></div>
   <div class="circle square"></div>
   <div class="circle square"></div>
   <div class="circle square"></div>   
   <div class="circle"></div>
   <div class="circle"></div> 
   <div class="circle"></div>
</div>
```

```css
.circle {
  border-radius: 100%;
  height: 100px;
  width: 100px;
  border: 2px solid #000000;
  margin: 10px;
}

.square {
  border-radius: 0%;
}

.flexContainer {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
}
```

<figure><img src="/files/iH5OdMkw49Wbr3Vt9Pli" alt=""><figcaption><p>flex, flex-direction, flex-wrap</p></figcaption></figure>

It is actually possible to combine the `flex-direction` and `flex-wrap` properties, to do this use the `flex-flow` property and apply both values within. This will be shown in the next example.

At this stage its possible to see the awesome power of flex and how it can be used within Software Engineering to create dynamic and re-sizeable user interfaces. Lets talk about another flex property that will be extremely helpful. `justify-content`, this property is used to align the "flex items" horizontally within the "flex container".

```css
.circle {
  border-radius: 100%;
  height: 100px;
  width: 100px;
  border: 2px solid #000000;
  margin: 10px;
}

.square {
  border-radius: 0%;
}

.flexContainer {
  display: flex;
  flex-flow: row wrap;
  justify-content: center;
}
```

```html
<div class="flexContainer">
   <div class="circle"></div>
   <div class="circle"></div> 
   <div class="circle"></div>
   <div class="circle"></div>
   <div class="circle"></div> 
   <div class="circle"></div>
   <div class="circle"></div>
   <div class="circle"></div> 
   <div class="circle"></div>
   <div class="circle square"></div>
   <div class="circle square"></div>
   <div class="circle square"></div>   
   <div class="circle"></div>
   <div class="circle"></div> 
   <div class="circle"></div>
</div>
```

<figure><img src="/files/qk7lmzXBveJ0zNB6gZeK" alt=""><figcaption><p>flex, flex-direction, flex-wrap, justify-content</p></figcaption></figure>

As you can see the "flex elements" have been centered within the container, and wrap when there isn't enough space for the overflow elements. You can use this property with a few values, not just 'center'.

#### justify-content values

| Value         | Description                                                           |
| ------------- | --------------------------------------------------------------------- |
| flex-start    | Default value. Items are positioned at the beginning of the container |
| flex-end      | Items are positioned at the end of the container                      |
| center        | Items are positioned in the center of the container                   |
| space-between | Items will have space between them                                    |
| space-around  | Items will have space before, between, and after them                 |
| space-evenly  | Items will have equal space around them                               |

To get truly centered content, we need to align the items to the center vertically as well as horizontally. To do this we can use the `align-items` property, just be aware that you need to specify a `height` to the "flex-container", or this may not work correctly. This property will align the content vertically to the container.&#x20;

```css
.circle {
  border-radius: 100%;
  height: 100px;
  width: 100px;
  border: 2px solid #000000;
  margin: 10px;
}

.square {
  border-radius: 0%;
}

.flexContainer {
  display: flex;
  flex-flow: row wrap;
  justify-content: center;
  align-items: center;
  height: 100vh;
}
```

```html
<div class="flexContainer">
   <div class="circle"></div>
   <div class="circle"></div> 
   <div class="circle"></div>
   <div class="circle"></div>
   <div class="circle"></div> 
   <div class="circle"></div>
   <div class="circle"></div>
   <div class="circle"></div> 
   <div class="circle"></div>
   <div class="circle square"></div>
   <div class="circle square"></div>
   <div class="circle square"></div>   
   <div class="circle"></div>
   <div class="circle"></div> 
   <div class="circle"></div>
</div>
```

You should note that you can apply other values than center, similar to `justify-content`.

| Value      | Description                                                                                                      |
| ---------- | ---------------------------------------------------------------------------------------------------------------- |
| normal     | Default. Behaves like 'stretch' for flexbox and grid items, or 'start' for grid items with a defined block size. |
| stretch    | Items are stretched to fit the container                                                                         |
| center     | Items are positioned at the center of the container                                                              |
| flex-start | Items are positioned at the beginning of the container                                                           |
| flex-end   | Items are positioned at the end of the container                                                                 |
| baseline   | Items are positioned at the baseline of the container                                                            |

As you can see from the image below the "flex-items" are centered horizontally and vertically within the image. This is a common pattern that is used when applying flex onto websites.&#x20;

<figure><img src="/files/jur0vqSYeFCsqAEeMnA9" alt=""><figcaption><p>flex, flex-direction, flex-wrap, justify-content, align-items</p></figcaption></figure>

To truly become great at flex, please go through the exercises below, this will help you greatly when considering your user interfaces, which is what you users will ultimately see.&#x20;

### Exercises

1. Watch [Flexbox in 100 Seconds video](https://www.youtube.com/watch?v=K74l26pE4YA) to know what flexbox is
2. Complete [Flexbox Froggy game](https://flexboxfroggy.com/) to practise flexbox
3. Complete [W3Schools flexbox tutorial](https://www.w3schools.com/css/css3_flexbox.asp) to read about and play with basic flexbox
4. Review [CSS Tricks flexbox cheatsheet](https://css-tricks.com/snippets/css/a-guide-to-flexbox/) on all flex container and flex item CSS properties
5. (Optional) Complete [Flexbox Defense game](http://www.flexboxdefense.com/) to practise flexbox


# 1.3: React

Learning Objectives

1. React is a frontend framework and library that allows us to create custom, nest-able UI elements with a combination of HTML and JavaScript syntax (JSX)
2. How to write JSX
3. How to write and render Functional based React components
4. How to use props
5. How to use state
6. What are component lifecycles and lifecycle methods
7. How to handle JS events in React
8. How to design component architecture

## Introduction

[React](https://legacy.reactjs.org/) is a frontend framework and library that allows us to create custom, nest-able UI elements with a combination of HTML and JavaScript syntax (JSX). React's HTML-like structure makes it easy to visualise, and its integrated JS makes it easy to render dynamic data. Alternative but less popular frontend libraries include [Vue](https://vuejs.org) and [Angular](https://angularjs.org).

We will use React's official [guide](https://react.dev/learn) and [tutorial](https://react.dev/learn/tutorial-tic-tac-toe) to learn React, and the [Vitejs](https://vitejs.dev/guide/) environment to scaffold our first React apps. Vite is a build tool that provides a fast and lean development experience for modern web projects. Vite leverages new advancements in the JavaScript ecosystems, the ability of native ES modules within the browser and the rise of JavaScript tools written in compile-to-native languages. This is because browsers do not read React natively; they read HTML, CSS and JS, not JSX.&#x20;

The following sections provide Rocket's annotations to React's official [guide](https://react.dev/learn) and [tutorial](https://react.dev/learn/tutorial-tic-tac-toe) to explain concepts that the React team assumes readers know.

## Day 5

### 1: [Hello World](https://react.dev/reference/react-dom/client/createRoot#usage)

In this section you should begin to understand that React applications are bound to a single root, this code is generated when we start a new React application using [Vitejs](https://vitejs.dev/guide/). Give this a shot yourself and generate a new React application with [Vitejs](https://vitejs.dev/guide/), you should be able to see a similar file structure to the official documentation above.&#x20;

To create a new React application using Vite, open up your CLI tool and run this command in the directory where you want to create your application:

`npm create vite@latest`

You will be prompted to input a name.

Then you will be asked what type of application you want to create, use your arrow keys to navigate to 'React' and press 'enter'.

Then using arrow keys once more navigate down to 'JavaScript', if you don't need standard build tools later in development you can choose 'JavaScript + SWC' and click enter.&#x20;

Now you can follow the instructions within the CLI to first navigate into the newly created directory, then install the required dependancies and finally run the React application using the command `npm run dev`, to view the application you should open the URL that is shown in your CLI, it should be something like [**http://localhost:5173**](http://localhost:5173/), the output on the page should be similar to the image below. &#x20;

<figure><img src="/files/rA9Mn2sW1CVmLc25L7eK" alt=""><figcaption><p>Vite and React</p></figcaption></figure>

There are some key files that you should be aware of within this starter code. Note that the index.html is in the root of the project directory, it is in the entry point to your application and is required for the React App. Please explore the files within the starter code and consider the points below,

1. Within the src/main.jsx file `document.getElementById('root')` is a DOM (Document Object Model) command that retrieves the HTML element with ID "root". React renders our app inside that element. React removes the need to write DOM code and the above command is the only DOM command we will need.
2. <mark style="color:red;">**Note**</mark> that if you want to add and use images within your Vite React applications please add the images into the `public` directory and import as usual.&#x20;
3. Rocket recommends that you familiarise yourself with as many of the provided examples as you can to understand and digest the relevant concepts
4. Rocket recommends completing most of the "Learn React" guide before attempting the "Tutorial: Tic Tac Toe" so the tutorial's concepts sink in better
5. If there is anything you do not understand in the guide, please let your SL know and we can include it in these notes!

### 2: [Introducing JSX](https://react.dev/learn/writing-markup-with-jsx)

JSX or JavaScript and XML affords developers the opportunity to write HTML-like markup within a JavaScript or JSX file. Without using JSX developers would be forced to utilise React [createElement](https://react.dev/reference/react/createElement), this is less readable and intuitive than JSX. By employing JSX we can combine rendering logic alongside markup within what developers name components. While JSX looks like HTML it is stricter and can display dynamic information. It should be noted that JSX has its own rules that should be followed.&#x20;

1. JSX elements may only return a single root element, to display multiple elements just wrap them within a single parent tag.&#x20;
2. Close all HTML tags.
3. DOM stands for "Document Object Model", which is a JavaScript representation of HTML rendered on a web page. Frontend frameworks like React use the DOM to programmatically manipulate UI without manually specifying HTML. Rocket recommends [W3School's intro to JavaScript HTML DOM](https://www.w3schools.com/js/js_htmldom.asp) (just the 1st page) for a primer. For Rocket's Bootcamp we can stop at DOM Intro without reading W3School's subsequent pages on DOM.
4. Use camelCase for most if its props,[ click here for more details](https://react.dev/learn/writing-markup-with-jsx#3-camelcase-salls-most-of-the-things). To apply CSS classes to JSX elements we will need to use the `className` keyword instead of `class`, which we used with vanilla HTML. This is because `class` is a reserved keyword in JS used to declare classes (which we will see in 4: Components and Props below).

### 3: [JavaScript in JSX](https://react.dev/learn/javascript-in-jsx-with-curly-braces)

Within JSX, "{ }" or "curly braces" allow developers to write and execute JavaScript bound to the HTML-like code. This makes JSX more dynamic than HTML and allows for data binding basically straight out of the box.&#x20;

1. When you want to add JavaScript logic or code into JSX you are able to do so by using curly braces within the JSX. Think of these using these braces { } like a window into the world of JavaScript.&#x20;
2. You can pass string attributes to JSX, do this using single or double quotations.
3. You can only use curly braces as text directly within a JSX tag **OR** as attributes immediately following the `=` sign.
4. You should use double curly braces in some instances when writing JSX. Such as using inline CSS or passing a js object into a JSX element. &#x20;

React follows what we call a "declarative" UI paradigm, where we tell our computers how the UI should look, but not how to achieve that look. The declarative paradigm is a layer on top of the "imperative" paradigm of DOM manipulation more commonly used before React.

## Post-Class Exercises: Codecademy React 101&#x20;

Complete all exercises in the following Codecademy lessons when they are assigned in the Rocket course schedule.

1. JSX
   1. [Intro to JSX](https://www.codecademy.com/courses/react-101/lessons/react-jsx-intro/exercises/why-react)
   2. [Advanced JSX](https://www.codecademy.com/courses/react-101/lessons/react-jsx-advanced/exercises/jsx-classname-class)

## Day 6

### 4: [React Components](https://react.dev/learn/your-first-component)

The concept of Components is core to React, they are the foundation of our React code, we use components to build user interfaces. This makes them ideal starting points once you've understood the basics of React JSX. React allows developers to combine markup, CSS and JavaScript into components that could be reusable UI elements within your application. Similarly to HTML tags we can compose, order and nest components to develop full pages within React applications. When building a Component follow these rules:

1. Export the Component&#x20;
2. Define the Component function
3. Add any markup required, this is what we want to display within the Component
4. Render the Component onto the React Application by nesting it into the App.jsx
5. [User-defined components must be capitalised](https://reactjs.org/docs/jsx-in-depth.html#user-defined-components-must-be-capitalized). Otherwise React will think they are HTML tags.

### 5: [Component Props](https://react.dev/learn/passing-props-to-a-component)

React components can communicate with each other via props, a parent may pass information down to child component and this data always flows downwards. There will be some familiar props associated to JSX tags, but you you can actually pass anything from a parent its children.

1. To pass props specify the information that should be passed from the parent to the child.
2. Access the prop information that was passed to the child component and set default values if required.
3. You can pass anything as a prop from a parent component to a child, you can access props by destructuring the individually passed sets of information or by referring to props.
4. Props are immutable, checkout [this example](https://react.dev/learn/passing-props-to-a-component#how-props-change-over-time) to see how they can change over time.

## Introduction to React Hooks

React Hooks are a newer and more efficient syntax for React Components. They allow us to write all components as functional components, and use so-called "Hook" functions to replace class component functionality such as state management and lifecycle methods. Components with hooks are functionally the same as class components.

Rocket recommends using Hooks in our exercises and projects from now on because Hooks are a cleaner syntax and the [React team recommends using Hooks for new projects](https://reactjs.org/docs/hooks-faq.html#should-i-use-hooks-classes-or-a-mix-of-both). The React team is [re-writing the official React tutorials to use Hooks](https://beta.reactjs.org/). React Router v6 (the latest and greatest version of React Router) that we are about to learn only supports React Hooks syntax natively, and Rocket recommends using Hooks to enable us to use the latest React Router features.

## Introducing Hooks

{% embed url="<https://reactjs.org/docs/hooks-intro.html>" %}

1. Many companies will still be using [Class based React Components](https://legacy.reactjs.org/docs/react-component.html) in their code. It will be important for us to still understand class Components, but know how to write Components with Hooks for new code to take advantage of latest React functionality. If you want to explore how to use state and lifecycles in React Class based Components you can read [this documentation](https://legacy.reactjs.org/docs/state-and-lifecycle.html).&#x20;

## Hooks at a Glance

This page is an overview of all of the subsequent tutorial pages. The subsequent pages go into more depth on each topic.

{% embed url="<https://reactjs.org/docs/hooks-overview.html>" %}

1. React Hooks provide all the functionality we need from React Class based Components that we didn't previously have with Functional Components of the past.
2. `useState` hook replaces `this.state` and `this.setState` with a new pair of variables for getting and setting a specific state value.
3. Note how the React team [encourages us to use multiple `useState` Hooks](https://reactjs.org/docs/hooks-faq.html#should-i-use-one-or-many-state-variables) in the same component for each type of state. There is no need to store all of a component's state in a single `this.state` object like we did previously.
4. Returning a cleanup function from `useEffect` is advanced functionality and we will not be using it as often at Rocket
5. We will not be writing custom Hooks at Rocket; feel free to skim through the "Building Your Own Hooks" section
6. We will learn about `useContext` and `useReducer` hooks in a later submodule.

## Using the State Hook

We will use the `useState` Hook most often. Clear explanations of what the `useState` Hook is and how to use it.

{% embed url="<https://reactjs.org/docs/hooks-state.html>" %}

1. Rocket strongly recommends following the naming convention of `X` and `setX` as the de-structured state variable names from `useState`. This makes our code more readable because other engineers will immediately know what each variable is for.

### Sample useState Hook

{% embed url="<https://youtu.be/eb6HKsxHoas>" %}
React Hooks useState
{% endembed %}

### 6: [React State management, useState](https://react.dev/learn/managing-state)

While creating your application and enlarging functionalities you will find that you are developing your components and states into much larger and complex files than you had before. IT is important to manage state effectively and reduce redundant or duplicated states within your application.&#x20;

1. When using useState to manage component state Rocket advises following these steps
   1. Import the useState hook from the react package, at the top of the component file
   2. Within your functional component declare a state variable and the updater function using the useState hook. As shown on [line 4](https://react.dev/learn/managing-state#reacting-to-input-with-state).&#x20;
   3. The initialValue of the state is passed into useState.
   4. You can update this variable using the updater function.
2. We will take a longer look onto useContext and useReducer later in this course.
3. When developing your state, group information if two state variables always change together, therefore unify them into a single state variable. Here are some more rules regarding [state structure](https://react.dev/learn/choosing-the-state-structure).
4. When updating a state variable its possible to use its current value, this is done by invoking a callback function on the updater function. Take a look at [these examples here](https://react.dev/reference/react/useState#updating-state-based-on-the-previous-state).

## Using the useEffect Hook

At Rocket we will use `useEffect` instead of the lifeCycleMethod `componentDidMount` for setting up subscriptions such as Firebase listeners and for data fetching. `useEffect` also allows us to perform functionality that was previously provided by `componentDidUpdate` and `componentWillUnmount`, but we will use that functionality less often.

{% embed url="<https://reactjs.org/docs/hooks-effect.html>" %}

1. As the docs mention, we can think of `useEffect` as running after the component renders.
2. A memory leak is when data that we use in parts of our apps is not properly cleaned up after the app stops using those parts. This can cause our apps to run slowly and even crash if the "leaks" cause our computers to run out of memory while running our apps. This will rarely happen to use in practice because JavaScript has automatic memory management and our apps will not be the most complex for now.
3. Returning a cleanup function from `useEffect` is optional and we will not use it often at Rocket.
4. No need to worry too much about "Optimizing Performance by Skipping Effects"; we will rarely need this and we can come back to it once we're more familiar with using `useEffect` and Hooks in general.

## Rules of Hooks

Rocket uses Create React App for our projects that includes the ESLint plugin for Hooks, so ESLint should enforce these rules for us by default.

{% embed url="<https://reactjs.org/docs/hooks-rules.html>" %}

### Sample useEffect Hook

{% embed url="<https://youtu.be/z4eeYjk57aM>" %}
React Hooks useEffect
{% endembed %}

### 7: [Component LifeCycles](https://react.dev/learn/lifecycle-of-reactive-effects) & [useEffect](https://react.dev/learn/synchronizing-with-effects#how-to-write-an-effect)

While developing React components it is possible to embed executable code within a component that runs on certain conditions. A common and useful pattern developers employ would be to call an API after the Component loads to get some information to display within the application. This can be controlled by the `useEffect` hook that is part of ReactJs.&#x20;

1. Understand a components lifecycle and how they are "mounted", "updated" and "unmounted".
2. In React we use effects to describe how to synchronise  an external system to the current prop and state.&#x20;
3. Understand how useEffect is implemented in components and what are the triggers that will force them to execute code
   1. Import the useEffect hook from the react package, at the top of the component file
   2. Call it at the top level of the component and put in your code, note state updates must be handled using conditional statements
   3. Handle effect with dependencies, inside the dependency array, passed as the second argument to useEffect
   4. Handle any effect clean ups by implemented a cleanup function within the effect.&#x20;
4. [React's offical guide and additional reference](https://react.dev/reference/react/useEffect) to the useEffect hook

## Post-Class Exercises: Codecademy React 101

Complete all exercises in the following Codecademy lessons when they are assigned in the Rocket course schedule.

1. React Components
   1. [Your First React Component](https://www.codecademy.com/courses/react-101/lessons/your-first-react-component/exercises/hello-world-component)
   2. [Components and Advanced JSX](https://www.codecademy.com/courses/react-101/lessons/react-components-advanced-jsx/exercises/render-multiline-jsx)
   3. [Components Render Other Components](https://www.codecademy.com/courses/react-101/lessons/components-render-each-other/exercises/components-interacting-intro)
   4. [this.props](https://www.codecademy.com/courses/react-101/lessons/this-props/exercises/this-props-intro)
2. Hooks
   1. [Function Components](https://www.codecademy.com/courses/react-101/lessons/stateless-functional-components/exercises/stateless-functional-component-intro)
   2. [The State Hook](https://www.codecademy.com/courses/react-101/lessons/the-state-hook)
   3. [The Effect Hook](https://www.codecademy.com/courses/react-101/lessons/the-effect-hook/exercises/function-component-effects)

## Additional Resources

The following resources are optional and can be used more for reference than upfront reading.

1. [Build Your Own Hooks](https://reactjs.org/docs/hooks-custom.html)
2. [Hooks API Reference](https://reactjs.org/docs/hooks-reference.html)
3. [Hooks FAQ](https://reactjs.org/docs/hooks-faq.html)

## Day 7

### 8: [Handling Events](https://react.dev/learn/responding-to-events)

When users click on a button they expect some result, or some change, take the counter example if you click on the button the state increments. To develop these types of functionality within our React applications we will need to handle events, but assigning an event listener to our elements and define some callback functions to handle the event in a meaningful way. In our JSX code we need to follow these steps to handle events.

1. How do you handle events?
   1. Attach the event listener to the element, such as an `onClick` or `onBlur` event.
   2. Define the callback function that will handle said event, accessing the event data if required. Remember to pass this function to the event handler.&#x20;
   3. Update state within this callback function by calling an updater function, run a side effect or execute any code.
2. "Events on DOM elements" are the same as [JavaScript events or HTML events](https://www.w3schools.com/js/js_events.asp). JS events allow us to perform logic on events that happen on our web pages such as mouse clicks. React supports a [wide range of events.](https://react.dev/reference/react-dom/components/common#common-props)
3. Remember that functions that are passed to event handlers must be passed and not called, you can wrap the given function in an anonymous function if you need to pass in arguments.
4. You are able to stop event propagation as well as the default action.

### 7: [Conditional Rendering](https://react.dev/learn/conditional-rendering)

Components will often need to display different UI's depending on conditions passed down as props, or the information its processing. You are able to conditionally render JSX in React using various patterns within JavaScript including conditonal statements that return JSX, or [ternary operators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_operator).

1. Conditional rendering is one of the most powerful features of React, enabling us to use conditional logic to specify what a component should render.
2. You can use inline code for conditionals, `condition ? true : false` syntax is the [JavaScript conditional operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator).

### 8: [Lists and Keys](https://react.dev/learn/rendering-lists)

Lables on cds and JSX keys in an array serve similar purposes, it helps us to identify unique items from thier siblings. Keys help React to identify different JSX elements throughout thier lifetimes. You can generate key values in whatever way you would like, but if you've pulled data out of a database, they might already have identities, such as an Id property. You could create you're own incrementing counter to set unique keys within an application or implement [uuid](https://www.npmjs.com/package/uuid) or another packaged that can assign unique id's within an application.&#x20;

1. Rocket recommends always using keys when rendering JSX elements in a list for performance reasons.
2. Keys should be unique among siblings
3. Keys cannot change as that would defeat the purpose of them

## Day 8

### 9: [Forms](https://react.dev/reference/react-dom/components#form-components), [input](https://react.dev/reference/react-dom/components/input), [select](https://react.dev/reference/react-dom/components/select), [textarea](https://react.dev/reference/react-dom/components/textarea)

HTML forms and their elements afford developers the opportunity to capture user information as they interact with our application. Forms can be composed of a combination of inputs, selects and textareas, when wrapped in a form tag the values of these inputs can be extracted as form data. Or they can be maintained purely using state. Employ React element such as input, select and text areas to give users different input capabilities.&#x20;

1. An [HTML form](https://www.w3schools.com/html/html_forms.asp) is an HTML element that either refreshes the page or navigates to a new page when the user submits the form. We often do not want this behaviour in React, opting to update UI on submit without refresh. To disable "refresh on submit" behaviour, Rocket recommends the technique in the React docs, to provide the `form` a `handleSubmit` callback function that calls `event.preventDefault`.
2. When handling the submit method from a form you should target the `event.target.value` to get the current value of an input.&#x20;
3. You must control the form elements that you use within a React component, do this by passing the value prop to it and handling the associated event. [Have an in-depth look here](https://react.dev/reference/react-dom/components/input#controlling-an-input-with-a-state-variable).&#x20;
4. Note how you will need to create state to capture form data.

## Post-Class Exercises: Codecademy React 101&#x20;

Complete all exercises in the following Codecademy lessons when they are assigned in the Rocket course schedule.

1. [React Forms](https://www.codecademy.com/courses/react-101/lessons/react-forms/exercises/react-forms-intro)

### Day 9

### 10: [Lifting State Up](https://react.dev/learn/sharing-state-between-components)

Managing state on components can get challenging and confusing when you need to share data between multiple components.  Especially so while still having to preform live updates and dynamically render content. The process of lifting up state means your children components actually receive data as props. Instead of storing the data on each child, you store the data on a shared parent of both child components. &#x20;

1. It is important that we pass both the temperature value and handle-change function from `Accordian` to `Panel` so the app can maintain only 1 "source of truth" state for the active value in `Panel`. If it helps, Rocket recommends drawing the component hierarchy to visualise how data flows in the application and verifying our understanding with our classmates and section leader.

### Day 10

### 11: [Thinking In React](https://react.dev/learn/thinking-in-react)

Developing a user interfaces in React can be challenging. Instead of looking at a webpage as a whole, you should instead split it into sections or components, at this stage we can consider the states required for each component to correctly render as intended. To ensure that data follows correctly you then need to connect your components pass information or functions from parents to children.&#x20;

1. [JSON](https://www.w3schools.com/js/js_json_intro.asp) (JavaScript Object Notation) is a data format similar to JavaScript Objects, except can be used in text or file form. An API (Application Programming Interface) is typically a URL that manipulates and/or returns data. A JSON API is an API that returns data in JSON format, one of the most common formats to send and receive data on the internet.
2. Notice the example and how it passes updater function and state from the parent to the child, such that we can control and alter state.

### Day 11

### [Tutorial: Intro to React](https://react.dev/learn/tutorial-tic-tac-toe)

If you finish the React Guide pages above early, feel free to start and finish this tutorial early to have more time for [Project 1](/1-frontend/1.p-frontend-app).

1. Rocket recommends starting with Setup Option 1 (Write Code in Browser) to focus on understanding React. If you finish the tutorial and have time, do Setup Option 2 (Local Development Environment) and port your code over to understand how to use Create React App. We will use Create React App to develop all frontend projects at Rocket.
2. Rocket recommends using [React DevTools](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=en) whenever developing React apps. It can help us debug quicker.
3. Note the tutorial's recommendation to use `on[Event]` naming convention for props that represent events and `handle[Event]` for methods that handle events.

{% hint style="info" %}
**New to Rocket Academy?**

If you're not enrolled in Rocket's Bootcamp and visiting this page, [check out our website](https://www.rocketacademy.co/courses/bootcamp-course) to learn more about our Bootcamp course!
{% endhint %}


# Styling in ReactJs

ReactJs Styling

Learning Objectives

1. Understand how to implement Style within ReactJs
2. Style Components using in-line style
3. Style Components using Stylesheet and classes

## Introduction

In a previous section we introduced CSS, which is used to apply styles to HTML pages beautifying content. Within ReactJs we can use CSS in order style our rendered output, you can apply any CSS style within React. It should be noted that because we are writing JSX, there are some different rules than applying style in HTML. An important distinction is that the className property is used on JSX elements to apply classes, this is because the word class in JavaScript is a reserved key word. We can use the boilerplate code that is generated from the npx Create React Application, we actually have some built in styling. Below is an example of the boilerplate output.

<figure><img src="/files/dlXguVkbH6AcYgtoDhkj" alt=""><figcaption><p>Create React Application</p></figcaption></figure>

### In-line Styling

To apply style in ReactJs we can apply in-line style. This has the highest level of CSS precedence as it is evaluated last by the browser, at this stage the component is being styled by a stylesheet, but we can override this. To demonstrate this we will alter the text 'Edit src ....' such that it is bold and red.  A key difference that we can see below is that when applying in-line styling we write camelCased property names, not kebab-cased, like we would in pure HTML applications.

Go to the App.js file, alter the parent div of your local code to reflect the block below:

{% code title="" lineNumbers="true" %}

```jsx
 <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p style={{ color: "red", fontWeight: "bold" }}>
          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>
```

{% endcode %}

Notice how the opening p tag on line 4 contains a style property which equals to a double set of curly braces. This code specifies a style object, the properties within must be camelCased and the values must be written in strings. Moreover each property and value should be seperated by a common.

This is the resulting render in the browser.

<figure><img src="/files/61o0hNWn7datpOQXL4pe" alt=""><figcaption><p>Create React Application In-line style</p></figcaption></figure>

### Style Objects

Another way to apply style in ReactJs would be to use JavaScript style objects that are passed to the JSX using the style property. In order to do this we create a JavaScript object that contains style and value, apply that to the JSX element using the className. Checkout the code and sample output below:

```jsx
function App() {

  const customHeaderStyle = {
    fontWeight: "900",
    color: "#ffffff",
    textDecoration: "#1bdb22 wavy underline",
  };
  
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p style={{ color: "red", fontWeight: "bold" }}>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <h1 style={customHeaderStyle}>This new header</h1>
        <br />
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;
```

<figure><img src="/files/s4fcYdfPTUet83ZEPzPI" alt=""><figcaption><p>New header added </p></figcaption></figure>

If you have multiple style objects that are consistent and used across components you could make a .js file that contains all of the common properties and import them into necessary components.&#x20;

### Stylesheets React

Another way one can apply style within Reactjs is through the stylesheet, as stated previously the App.js component is already affect by some boilerplate style, that should be found in App.css. We can alter the content further by adding new classes into the App.css stylesheet and by adding new classes to our App.js code.&#x20;

Lets change the link below to remove all text decoration such that we can apply our own style.

Alter your App.css, target the App-link class to reflect the code below:

```css
.App-link {
  color: #3324bd;
  font-weight: bold;
  text-decoration: none;
  border: 2px solid #ff0000;
  background-color: #ffffff;
}
```

The output should look like this within the browser.

<figure><img src="/files/DzwkATSfd75AaYqEpZWe" alt=""><figcaption><p>Stylesheet applied</p></figcaption></figure>

Stylesheets are used within the Application by importing them at the top of the component. The full component should be similar to the code below.

{% code lineNumbers="true" %}

```jsx
import logo from "./logo.svg";
import "./App.css";

function App() {

const customHeaderStyle = {
    fontWeight: "900",
    color: "#ffffff",
    textDecoration: "#1bdb22 wavy underline",
  };
  
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p style={{ color: "Red", fontWeight: "bold" }}>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <h1 style={customHeaderStyle}>This new header</h1>
        <br />
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;
```

{% endcode %}

In the component above we can see that we apply classes to JSX tags using the property className. It is possible to apply more than one className to a JSX tag just like in HTML. Generally when creating React applications developers would create common stylesheets for style that is consistent across components, and individual stylesheets for unique components that do not share style with other parts of the application.&#x20;


# Using Styling Libraries with React

Learning Objectives

1. Understand what React-Bootstrap is
2. Implement React-Bootstrap into React Applications
3. Using React-Bootstrap pre-styled components

### React Bootstrap Initialisation

React Bootstrap is a popular frontend styling library, it contains pre-built style and functionalities for out of the box easy implementation. This tool is integrated well with ReactJs and is geared for beginners to test out and implement styling libraries. Developers are even able to customize Bootstrap within custom scss stylesheets, feel free to learn more about it [here](https://react-bootstrap.github.io/getting-started/introduction#customize-bootstrap).&#x20;

To implement React Bootstrap into a React application open a CLI interface and change directory to your current project. Here you can run this command:

```
npm install react-bootstrap bootstrap
```

This will install React Bootstrap and the bootstrap package within the application, there is still one more step that must be taken before you can utilise all of React-Bootstrap in your app.

Go to the main.jsx within your React application and this line at the top of the file:

```jsx
import 'bootstrap/dist/css/bootstrap.min.css';
```

This line imports the CSS for bootstrap into your application, any child components of this file will be able to access and utilise React-Bootstrap styling, pre-made components, utilities and alignment system.&#x20;

Now that Bootstrap has been implemented in your application it might be a good idea to look at some of the pre-styled components you can implement, look at some examples and usage [here](https://react-bootstrap.github.io/components/alerts/).

To showcase implementing React Bootstrap into a React Application we will implement some new styled buttons on our previously edited boilerplate code from our previous section.

### React Bootstrap Component&#x20;

We will import Button from react-bootstrap such that we get pre-styled buttons without much effort. Alter the App.js file to reflect code below:

{% code lineNumbers="true" %}

```jsx
import logo from "./logo.svg";
import "./App.css";
import { Button } from "react-bootstrap";

function App() {

const customHeaderStyle = {
    fontWeight: "900",
    color: "#ffffff",
    textDecoration: "#1bdb22 wavy underline",
  };
  
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p style={{ color: "Red", fontWeight: "bold" }}>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <h1 style={customHeaderStyle}>This new header</h1>
        <br />
        <Button variant="primary">Bootstrap Button</Button>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;
```

{% endcode %}

The output on the browser is as follows:

<figure><img src="/files/Q7SnUOL4LeUJw7t3yXtP" alt=""><figcaption><p>Bootstrap added</p></figcaption></figure>

From the image above we can see a new blue button has been added into the application, we didnt style this button, it was all React-Bootstrap. This is how you can utilise React-Bootstrap within a React application. Utilise more complex components using this styling library to save yourself time during development.

Checkout more React-Bootstrap Components [here](https://react-bootstrap.netlify.app/docs/components/accordion). Use a combination of pre-styled and custom components to quickly develop applications that can be tailored to your need, just be aware of the props that you can pass. Constantly run your React application to see whether or not your application is being styled appropriately. And remember when styling with React-Bootstrap you just need to import the component's that you need at the top of the page, then you can use them like normal HTML tags in your JSX.

### React Bootstrap Grid System

One of the most powerful features of React-Bootstrap is its grid system, which facilitates mobile responsive websites without having to restyle every single element on your page. Learn more about the grid system:

{% embed url="<https://react-bootstrap.netlify.app/docs/layout/grid/>" %}
Grid System React Bootstrap
{% endembed %}

When implementing the grid system be sure to:

1. Use a react-bootstrap `Container` Component
2. Use `Row` and `Column` Components within the `Container` to display your information
   1. Note that each row can be broken into 12 columns
   2. Each section can take up multiple spaces
3. Uncover and understand the [Breakpoint system](https://react-bootstrap.netlify.app/docs/layout/breakpoints) in react-bootstrap
4. Wire-framing and planning out how your component will look will make using grid easier

Here is a simple implementation of the react-bootstrap grid system

```jsx
 <Container>
          <Row>
            <Col style={columnStyle}> 1 of 1</Col>
          </Row>
          <br />
          <Row>
            <Col style={columnStyle}> 1 of 2</Col>
            <Col style={columnStyle}> 2 of 2</Col>
          </Row>
          <br />
          <Row>
            <Col style={columnStyle}> 1 of 4</Col>
            <Col style={columnStyle}> 2 of 4</Col>
            <Col style={columnStyle}> 3 of 4</Col>
            <Col style={columnStyle}> 4 of 4</Col>
          </Row>
          <br />
          <Row>
            <Col style={columnStyle}> 1 of 6</Col>
            <Col style={columnStyle}> 2 of 6</Col>
            <Col style={columnStyle}> 3 of 6</Col>
            <Col style={columnStyle}> 4 of 6</Col>
            <Col style={columnStyle}> 5 of 6</Col>
            <Col style={columnStyle}> 6 of 6</Col>
          </Row>
 </Container>
```

<figure><img src="/files/liKVizxzwZYKucE6FqXK" alt=""><figcaption><p>Simple Grid System</p></figcaption></figure>

It is possible to make the `Col` Components respond to the windows width, based off the breakpoints that were pointed out earlier. This allows columns to wrap and resize their content to ensure that data is shown exactly as intended, to do this we need to make use of Bootstraps breakpoint properties on our `Col` Components as shown below. You are able to apply as many breakpoint properties on a `Col` as are needed.&#x20;

<pre class="language-jsx"><code class="lang-jsx">&#x3C;Container>
          &#x3C;Row>
          
          {/* 
            xl = On an extra large screen the Col takes up the full width of the Container
            lg = On a large screen the Col takes up half the width of the Container
            md = On a medium screen the Col takes up a third of the width of the Container
            sm = On a small screen the Col takes up a quarter of the width of the Container
            This allows the columns to dynamically alter depending on the window size that the user is using. 
          */}
            
            &#x3C;Col style={columnStyle} xl={12} lg={6} md={4} sm={3}>
              1 of 6
            &#x3C;/Col>
            &#x3C;Col style={columnStyle} xl={12} lg={6} md={4} sm={3}>
              2 of 6
            &#x3C;/Col>
            &#x3C;Col style={columnStyle} xl={12} lg={6} md={4} sm={3}>
              3 of 6
            &#x3C;/Col>
            &#x3C;Col style={columnStyle} xl={12} lg={6} md={4} sm={3}>
              4 of 6
            &#x3C;/Col>
            &#x3C;Col style={columnStyle} xl={12} lg={6} md={4} sm={3}>
              5 of 6
            &#x3C;/Col>
            &#x3C;Col style={columnStyle} xl={12} lg={6} md={4} sm={3}>
              6 of 6
            &#x3C;/Col>
          &#x3C;/Row>
<strong>        &#x3C;/Container>
</strong></code></pre>

Below is the output of the code above, depending on the size of the window.

<figure><img src="/files/7OIISYVqlFIi9M4pvz0C" alt=""><figcaption><p>Extra Large Screen ≥1200px</p></figcaption></figure>

<figure><img src="/files/azFLUNMo2EYUFoPKvNfN" alt=""><figcaption><p>Large Screen ≥992px</p></figcaption></figure>

<figure><img src="/files/mVmLI3zUkkHYFhS62d7l" alt=""><figcaption><p>Medium Screen ≥768x</p></figcaption></figure>

<figure><img src="/files/0UBejriVsj6GFJ2JC13N" alt=""><figcaption><p>Small Screen ≥576px</p></figcaption></figure>

The Grid system in `react-bootstrap` affords developers an easy way to dynamically resize content dependant on their users screens. This system of Bootstrap Components comes together to build fully responsive webpages, it should be noted that the underlying system used here is flexbox. This system is a fantastic way to ensure that an applications content can be visible to users across multiple device sizes without the need to add in hundreds of @mediaqueries.&#x20;


# React Deployment

Please follow one of the following metbods.

## Vitejs Deployment: Github Pages using the gh-pages CLI tool

Navigate into your project via a CLI tool (ubuntu/ terminal)\
Go through gitflow and save your current code.&#x20;

```
git add
git commit -m 'commit-message'
git push 
```

Next, run the following command:&#x20;

`npm run build`

You can check to see if your build worked by running the command:&#x20;

`npm run preview`

\
You should be able to see your application within your browser at [`http://localhost:4173`](http://localhost:4173/)

After validating that this works, we will install the required packages:\
Run the command: `npm install gh-pages --save-dev`

Now we will setup the package.json:\
Add these scripts into scrips:

```
"predeploy": "npm run build",
"deploy": "gh-pages -d dist",
```

Now we will configure the vite.config.js:\
We need to add a key value pair for gh-pages:

The key will be base, the value should be ‘/name-of-your-repo’\
The configure should look something like:

```
export default defineConfig({
  plugins: [react()],
  base: "/ftbc14_vitejs/",
});
```

Now you should be able to run the command: `npm run deploy`

\#==========================================================#

## Vitejs Deployment: Github Pages through git push

Navigate into your project via a CLI tool (ubuntu/ terminal)

Go through gitflow and save your current code.&#x20;

```
git add
git commit -m 'commit-message'
git push 
```

Run the following command:&#x20;

`git checkout -b gh-pages`

Next, run the following command:&#x20;

`npm run build`

You can check to see if your build worked by running the command:&#x20;

`npm run preview`

\
You should be able to see your application within your browser at [`http://localhost:4173`](http://localhost:4173/)

Now we will configure the vite.config.js:\
We need to add a key value pair for deployment:

The key will be base, the value should be ‘/name-of-your-repo’\
The configure should look something like:

```
export default defineConfig({
  plugins: [react()],
  base: "/ftbc14_vitejs/",
});
```

Within your local machine we need to make a new github workflow within a yml file.

\
Create a new folder named `.github`\
Within the newly created directory create a workflows folder\
In the workflows folder create a new file named: `jekyll-gh-pages.yml`

Paste in this file:

```
# Simple workflow for deploying static content to GitHub Pages
name: Deploy static content to Pages

on:
  # Runs on pushes targeting the default branch
  push:
    branches: ["gh-pages"]

  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

# Sets the GITHUB_TOKEN permissions to allow deployment to GitHub Pages
permissions:
  contents: read
  pages: write
  id-token: write

# Allow one concurrent deployment
concurrency:
  group: "pages"
  cancel-in-progress: true

jobs:
  # Single deploy job since we're just deploying
  deploy:
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Setup Node.js environment
        uses: actions/setup-node@v4.0.0
        with:
          node-version: lts/*
          cache: 'npm'
      - name: Install dependencies
        run: npm install
      - name: Build
        run: npm run build
      - name: Setup Pages
        uses: actions/configure-pages@v3
      - name: Upload artifact
        uses: actions/upload-pages-artifact@v2
        with:
          # Upload entire repository
          path: './dist'
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v2
```

In your GitHub, repo goto pages and then choose source as GitHub actions, not deploy from branch. Now you should be able to deploy when you push to this branch, before this will work we need to go through git flow (add commit and push)\
Then run the command:&#x20;

`git push origin gh-pages`


# 1.E: Exercises


# 1.E.1: Recipe Site

## Learning Objectives

1. Know how to build an HTML site from scratch
2. Know how to use Git commits and GitHub pull requests

## Introduction

Create a website that showcases your favourite recipes.

## Instructions

1. Fork and clone a copy of [Rocket's Recipe Site repo](https://github.com/rocketacademy/recipe-site-bootcamp)
2. Google for at least 4 recipes from at least 2 cuisines and save an image of each dish in the repo
3. Create an HTML page for each recipe, where each page has the following info
   1. Recipe title
   2. Ingredients
   3. Preparation time
   4. Instructions
   5. Image of dish (use `img` tag referencing image saved in repo)
4. Create a home page that links to each recipe's page with an `a` tag. Create a link on each recipe page linking back to the home page.
5. The application is as follows:
   1. Pages should be set up in this manner.&#x20;

      <pre><code><strong>Homepage Listing Cuisines -> Cuisine Listing Recipes --> Recipe
      </strong></code></pre>
6. You will need to create sub pages for each cuisine and then sub pages for each recipe listed on the Cuisine pages.&#x20;
7. Deploy your site to the internet with [GitHub Pages](https://docs.github.com/en/pages/getting-started-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site)
8. Create a pull request to the `main` branch in Rocket's repo and share the PR link in your section Slack channel

## Reference Solution

Here is [reference code](https://github.com/rocketacademy/recipe-site-bootcamp/tree/solution) and a [reference deployment](https://rocketacademy.github.io/recipe-site-bootcamp/) for this exercise.


# 1.E.2: Portfolio Page

## Learning Objectives

1. Know how to make a professional-looking website with vanilla CSS rules and layout techniques

## Instructions

Make a professional-looking portfolio page with CSS rules and layout techniques. Feel free to use hard-coded dummy data and use flexbox to layout projects. [Here is a sample page](https://codepen.io/freeCodeCamp/full/zNBOYG) for reference.

Start by forking and cloning [Rocket's Portfolio Page repo](https://github.com/rocketacademy/portfolio-page-bootcamp). Submit by creating a pull request to the `main` branch of Rocket's repo and sharing the PR link in your section Slack channel.

## Reference solution

Here is [reference code](https://github.com/rocketacademy/portfolio-page-bootcamp/tree/solution) and a [reference deployment](https://rocketacademy.github.io/portfolio-page-bootcamp/) for this exercise. You can do better!


# 1.E.3: World Clock

## Learning Objectives

1. Understand how to install packages in an NPM project and start an NPM app
2. Understand how to mix JavaScript and HTML syntax with JSX to produce dynamic UIs
3. Understand how React loads through the DOM on a webpage
4. Understand how to store state in components and use that state to manipulate UI
5. Understand how to use component lifecycle methods to execute logic when the component mounts and unmounts
6. Understand how to encapsulate UI elements in components and pass parameters to them with props

## Introduction

We will build a collection of clocks with different time zones to demonstrate the fundamentals of React and Node apps.

## Starter Code

### Clone starter code

Fork and clone [Rocket's World Clock repo](https://github.com/rocketacademy/world-clock-3.2) (Rocket-themed React Vite application). Run `npm install` to install default packages our app needs to run, and run `npm run dev` to start the app next open your browser and navigate to [http://localhost:5173](http://localhost:5173/).

### Understand starter code

1. `README.md` contains instructions for running the app
2. `package.json` lists the packages our app needs to run as well as their versions in `dependencies`, its also contains `scripts` that ViteJs provides that are used to run and maintain the application. We can add as many new dependencies and scripts as we want, but we will not add any for this exercise to keep our app simple. We will not strictly need to, but if you are curious, read [`package.json` docs](https://docs.npmjs.com/cli/v8/configuring-npm/package-json) to understand its other attributes in more detail.
3. `package-lock.json` lists all dependencies of the packages that are listed in `package.json` as well as their versions and other required dependenies. This makes sure all dependency versions are standardised for consistency in running our app. We should never alter this file manually.
4. `node_modules` contains all dependency files installed by `npm install`. We should never modify `node_modules` directly nor commit it to GitHub because its contents can be re-generated on-demand with `npm install`, provided you've shared the `package.json`.
5. `src` contains our source code, i.e. our app logic. `src/main.jsx` renders our React app's root component into the root HTML page, and `App.jsx` defines our React app logic.
6. `public` contains static files to load the app website, including its favicon (icon in tab bar) root HTML page and manifest for SEO purposes. Remember, we place our image assets here.
7. `.gitignore` specifies files and folders that we should not commit to Git, such as `node_modules`.

## Base

{% hint style="info" %}
**Hint: View changes in browser while coding**

Run app with `npm start` to view latest changes in browser while writing app logic. If you haven't already, install packages with `npm install` from the root of the repo before running `npm run dev`.
{% endhint %}

### Mix JavaScript and HTML syntax in JSX

`src/App.jsx` contains the `App Component`, the root React element, in our React app and we will write our clock app logic there.&#x20;

Notice the starter code in `App.jsx` contains mostly HTML. Let's add JavaScript to it to render a date. Replace the `return` statement with the following code.

{% code title="src/App.jsx" %}

```jsx
  return (
    <>
      <div>
        <img src={logo} className="logo" alt="Rocket logo" />
      </div>
      <h1>World Clock</h1>
      <div className="card">
        <p>
          Edit <code>src/App.jsx</code> and save to test HMR
        </p>
        <p>{new Date().toString()}</p>
      </div>
    </>
  );
```

{% endcode %}

Notice we have declared a new [JavaScript Date object](https://www.w3schools.com/js/js_dates.asp) from within the `<p>` tags and told React to render that date as a string in our UI. This is possible because React supports JSX syntax that enables mixing of HTML and JavaScript. Feel free to add more JavaScript elements in JSX with curly braces `{}` like we did with the date.

### Render current date and time every second

`src/main.jsx` is where we render the root React element of our React app. Let's observe how we can update it to render the current date and time every second to simulate a clock.

Comment out the code that renders `App` in `main.jsx` and add the following `tick` function and `setInterval` function call below it. Save the file to observe changes in the browser.

{% code title="src/main.jsx" %}

```jsx
{/*
ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
)
*/}

function tick() {
  const element = (
    <div>
      <h1>Hello, world!</h1>
      <h2>It is {new Date().toLocaleTimeString()}.</h2>
    </div>
  );
  root.render(element);
}

setInterval(tick, 1000);

const root = ReactDOM.createRoot(document.getElementById("root"));

```

{% endcode %}

Notice our app now displays a digital timestamp that updates every second within the browser.

`setInterval` calls the function in its 1st parameter at the interval specified by the number of milliseconds in its 2nd parameter. In this case it is re-assigning the data and time via the `new Date()` method and re-rendering the UI every second.&#x20;

We should also consider how we have altered the original render method. We assign the `ReactDom.createRoot(document.getElementById('root'))` to a variable named root, such that we can call the render method within the `tick` function.&#x20;

Notice the value of `element` in `tick` looks similar to the element returned in the `return` statement within the `App.jsx`, that being, HTML with a JavaScript date inserted using curly braces `{}` in JSX.

The difference between `main.jsx` and `App.jsx` is the `setInterval` in `main.jsx` that calls `tick` and hence `root.render` method every second.&#x20;

## Comfortable (Second day)

### `setInterval` inside the `App` component

{% hint style="warning" %}
Requires students to have reviewed Components and Props, React Hooks State and Lifecycle sections of React docs
{% endhint %}

What if our app had more UI elements than just the clock and we did not want to re-render the root element in `main.jsx` every second? Re-rendering the root element would be costly because it would re-render all components in our app, not just the clock.

Luckily components have lifecycle methods that run only on component mount, such that we can call `setInterval` from within a clock-specific React component without re-rendering the root element. We can achieve this using the useEffect hook. We will now move our clock logic into the `App` component so we do not need to modify the way we render our root element in `main.jsx`.

#### Undo changes in `main.jsx`

Undo the changes we made to `main.jsx` in the previous section. Our `main.jsx` file should now contain the following code below imports.

{% code title="src/main.jsx" %}

```jsx
import ReactDOM from "react-dom/client";
import App from "./App.jsx";
import "./index.css";

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
```

{% endcode %}

#### Add state to `App` component to store date and time in local state

Add state to our `App` component that will store the date and time that we will update every second in a state variable named `date`. Add the `date` state using the useState method from React, instead of calling `new Date()` in our `return` statement, update the JSX to read date from `date` variable instead. `date` will contain the current value of the `date` variable in component state. When calling the `useState` function pass new Date() as the intial value. Our `App` component should look like the following.

{% code title="src/App.jsx" %}

```jsx
import logo from "/logo.png";
import "./App.css";
import {useState} from 'react'

export default function App() {
  const [date, setDate] = useState(new Date())
  return (
    <>
      <div>
        <img src={logo} className="logo" alt="Rocket logo" />
      </div>
      <h1>World Clock</h1>
      <div className="card">
        {/* Render date value that is stored in state */}
        <p>{date.toString()}</p>
      </div>
    </>
  );
}
```

{% endcode %}

You may notice that the date is still static and doesn't change at this stage. We will now add the `setInterval` code to allow our clock to re-render every second from within the `App` component.

#### Add Component useEffect method to update the date state every second and teardown state-updating logic when Component unmount's

Import the `useEffect` hook from `React`,  we can implement this method above the `return` statement inside the `App` Component in `App.jsx`. Add a `setInterval` function call inside the `useEffect` method that updates the `date` variable in local state to a new date with `setDate` every second. Save the timer ID returned by `setInterval` variable such as `timerId`, and call `clearInterval` on that `timerId` within the teardown function that can be implemented in useEffect.

The clock in our UI should now automatically update every second! [Here](https://github.com/rocketacademy/world-clock-3.2/blob/setInterval_app_logic/src/App.jsx) is a reference solution for this section.

{% hint style="info" %}
**Full reference solution at bottom of page**

Rocket exercises will typically have a reference solution at the bottom of each exercise page. We will provide code examples inline for explanation, but otherwise we hope you will attempt the exercises on your own and review reference solutions afterward.
{% endhint %}

### Refactor clock display logic into its own Component

Imagine now that we wish to render multiple clocks to represent different time zones. We would like to do this inside `App` because `App` is the root Component.

Naively we could copy-paste our previous clock logic multiple times in `App` to achieve this, changing the parameters passed to `new Date()` in our `setInterval` callback function to set each date to a different timezone. This would cause much repeated code, violate the [DRY (don't repeat yourself) principle](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself), leading to increased chances of bugs in our code.

A better solution would be to encapsulate all clock logic in a new Component called `Clock`, and use the `Clock` Component multiples times in `App`, passing timezone information as a prop to each `Clock` Component for it to render the date and time of the relevant timezone.

#### Move clock logic into `Clock` Component

Create a new file `Clock.jsx` inside the `src` folder. Define a new React Component `Clock` inside (feel free to mimic the structure of `App.jsx`) with all clock-related logic from `App.jsx`. Remember to remove the `App`-specific HTML tags in the `return` statement (everything other than the `p` tags with date string), and to `export default` the `Clock` Component at the bottom of the file, or during function declaration.

#### Remove clock logic from `App` Component

Now that our clock logic is in `Clock.jsx`, remove all clock-related logic from `App.jsx` such that the `App` Component now only contains the `return` statement with two `div`s and a `h1` tag, note that the first `div` contains an image.

#### Import `Clock` and use it in `App`

Import our `Clock` Component from `App.jsx` with code like the following below the other imports in `App.jsx`.

```jsx
import Clock from "./Clock.jsx";
```

Use the `Clock` Component in the `return` statement of `App` where we used to have our `p` tags. For now, add a single `Clock` instance and verify that our clock works when we run our app. Our `return` statement might look like the following.

```jsx
  return (
   <>
      <div>
        <img src={logo} className="logo" alt="Rocket logo" />
      </div>
      <h1>World Clock</h1>
      <div className="card">
        <Clock />
      </div>
    </>
  );
```

We now have a clock that we can re-use in anywhere in our app with a single line of code! [Here](https://github.com/rocketacademy/world-clock-3.2/commit/7d5d46e54968058770bfd720ce97a0f86b5ba4f1) is a reference solution for this section

### Add timezone data to `Clock` via props

We will now add multiple clocks, each with a different time zone. Because clock logic for different time zones is the same except for time zone specification, we would not want to create a separate `Clock` Component for each time zone. Instead, we will modify `Clock` to accept time zone as a prop and render time according to the specified time zone. We will then declare multiple `Clock`s with different time zones in `App`.

#### Research how to display different time zones with JavaScript Dates

JavaScript Dates do not store dates in a specific time zone, but are able to render the date that they store in any time zone with a built-in [`toLocaleString`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleString) method. We can use `toLocaleString` like the following.

```javascript
const date = new Date();
date.toLocaleString('en-GB', { timeZone: 'Asia/Singapore' })
```

The first parameter to `toLocaleString` is a language code (see all legal language codes [here](https://www.w3schools.com/jsref/jsref_tolocalestring.asp#parameter-values)), and the 2nd parameter is an options object that allows us to specify time zone (see all valid time zones [here](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List) in "TZ database name" column).

Now that we know how to render a date in a specific time zone, we can accept a time zone string as a prop and use it to customise `Clock`!

#### Update rendered date string in `Clock` to use `toLocaleString` with time zone prop

Update the `return` statement in our `Clock` Component to render the date with `toLocaleString` instead of `toString`. Pass a language code (whichever you prefer) and time zone option as parameters to `toLocaleString`, where the time zone comes from props via `props.timeZone`.

In `App.jsx`, update our `App` component to render 3 clocks, each with a different time zone. Specify time zones with props like in the below code snippet. Feel free to pick whichever time zones are most relevant to you!

```jsx
<Clock timeZone="Asia/Singapore" />
```

#### Add time zone label to each clock

To make it clearer which time zone each clock is rendering, add a time zone label next to the date string in `Clock`'s `return` statement. This can be any string that represents the time zone.

Great job on making a clock app that shows multiple time zones! [Here ](https://github.com/rocketacademy/world-clock-3.2/tree/clock_component_prop/src)is a reference solution for this section. Don't forget to review the reference solution at the bottom of the page to see how Rocket implemented our full app. Coding is like writing an essay and there are many right answers, so don't fret if yours looks different.

## Improve clock UI with React Bootstrap grid system

Render time zone and time in separate columns with [React Bootstrap's grid system](https://react-bootstrap.github.io/docs/layout/grid) to make our clock information easier to parse. We may wish to implement the grid system and time zone labels in `App.jsx` such that our `Clock` component can just render the time for the relevant time zone.

The grid might look something like the following.

| City        | Clock                                      |
| ----------- | ------------------------------------------ |
| Los Angeles | `<Clock timeZone="America/Los_Angeles" />` |
| London      | `<Clock timeZone="Europe/London" />`       |
| Singapore   | `<Clock timeZone="Asia/Singapore" />`      |

## More Comfortable: `WorldClock` component with dynamic number of clocks

Refactor our world clock UI into its own component `WorldClock` in its own file such that others can use it to create world clock UIs with a custom number of clocks with a custom set of timezones. `WorldClock` should accept a `clockData` prop that is an array of time zone strings, where each string corresponds to a new clock. `WorldClock` should use the `Clock` component internally, and our `App` component should import and use `WorldClock`. You may find the upcoming reading in [Lists and Keys](https://react.dev/learn/rendering-lists) helpful for mapping an array of time zone strings to `Clock` components.

## Submission

Submit a pull request to the `main` branch of Rocket's World Clock repo and share your PR link in your section Slack channel.

If you would like to deploy your app to the internet, follow Vitejs GitHub Pages [deployment instructions here](https://vitejs.dev/guide/static-deploy.html). If those instructions are not clear please follow this section in the Gitbook.

## Reference Solution

Here is [reference code ](https://github.com/rocketacademy/world-clock-3.2/tree/solution-base/src)and a [reference deployment](https://rocketacademy.github.io/world-clock-3.2/) for this exercise. You can do better!


# 1.E.4: High Card

## Learning Objectives

1. Solidify knowledge of HTML, CSS and React by using it to build a standalone React app
2. How to deploy a React app to the internet

## Introduction

High Card is a turn-based game between 2 or more players where each player draws a card and the player with the highest card wins that round. The overall winner is the player that has won the most rounds when the deck runs out of cards. We will implement High Card with React.

## Starter Code

### Clone starter code

Fork and clone Rocket's [High Card repo](https://github.com/rocketacademy/high-card-3.2) (Rocket-themed Create React App) and understand the following starter code before creating High Card. Run `npm install` to install default packages our app needs to run, and run `npm run dev` to start the app next open your browser and navigate to [http://localhost:5173](http://localhost:5173/).

### Understand starter code

Notice a file `utils.jsx` (short for "utilities") in the `src` folder that contains helper functions for creating and shuffling a card deck. This is the same code we use in Coding Fundamentals.

{% code title="utils.jsx" %}

```javascript
// Get a random index ranging from 0 (inclusive) to max (exclusive).
const getRandomIndex = (max) => Math.floor(Math.random() * max);

// Shuffle an array of cards
const shuffleCards = (cards) => {
  // Loop over the card deck array once
  for (let currentIndex = 0; currentIndex < cards.length; currentIndex += 1) {
    // Select a random index in the deck
    const randomIndex = getRandomIndex(cards.length);
    // Select the card that corresponds to randomIndex
    const randomCard = cards[randomIndex];
    // Select the card that corresponds to currentIndex
    const currentCard = cards[currentIndex];
    // Swap positions of randomCard and currentCard in the deck
    cards[currentIndex] = randomCard;
    cards[randomIndex] = currentCard;
  }
  // Return the shuffled deck
  return cards;
};

const makeDeck = () => {
  // Initialise an empty deck array
  const newDeck = [];
  // Initialise an array of the 4 suits in our deck. We will loop over this array.
  const suits = ["Hearts", "Diamonds", "Clubs", "Spades"];

  // Loop over the suits array
  for (let suitIndex = 0; suitIndex < suits.length; suitIndex += 1) {
    // Store the current suit in a variable
    const currentSuit = suits[suitIndex];

    // Loop from 1 to 13 to create all cards for a given suit
    // Notice rankCounter starts at 1 and not 0, and ends at 13 and not 12.
    // This is an example of a loop without an array.
    for (let rankCounter = 1; rankCounter <= 13; rankCounter += 1) {
      // By default, card name and card rank are the same as rankCounter
      let cardName = `${rankCounter}`;
      let cardRank = rankCounter;

      // If rank is 1, 11, 12, or 13, set cardName to the ace or face card's name
      if (cardName === "1") {
        cardName = "Ace";
        // Ace has higher rank than all other cards
        cardRank = 14;
      } else if (cardName === "11") {
        cardName = "Jack";
      } else if (cardName === "12") {
        cardName = "Queen";
      } else if (cardName === "13") {
        cardName = "King";
      }

      // Create a new card with the current name, suit, and rank
      const card = {
        name: cardName,
        suit: currentSuit,
        rank: cardRank,
      };

      // Add the new card to the deck
      newDeck.push(card);
    }
  }

  // Return the completed card deck
  return newDeck;
};

// Export functionality to create a shuffled 52-card deck
export const makeShuffledDeck = () => shuffleCards(makeDeck());
```

{% endcode %}

Understand `App.jsx`'s logic to deal 2 cards at a time from the card deck. Understand what each line of code does before moving on, and ask your batch mates if you're not sure what the code is doing.

{% code title="App.jsx" %}

```jsx
import React from "react";
import "./App.css";
import { makeShuffledDeck } from "./utils.jsx";
import { useState } from "react";

function App(props) {
  // Set default value of card deck to new shuffled deck
  const [cardDeck] = useState(makeShuffledDeck());
  // currCards holds the cards from the current round
  const [currCards, setCurrCards] = useState([]);

  const dealCards = () => {
    const newCurrCards = [cardDeck.pop(), cardDeck.pop()];
    setCurrCards(newCurrCards);
  };
  
  // You can write JavaScript here, just don't try and set your state!

  // You can access your current components state here, as indicated below
  const currCardElems = currCards.map(({ name, suit }) => (
    // Give each list element a unique key
    <div key={`${name}${suit}`}>
      {name} of {suit}
    </div>
  ));

  return (
    <div className="App">
      <header className="App-header">
        <h2>React High Card 🚀</h2>
        {currCardElems}
        <br />
        <button onClick={dealCards}>Deal</button>
      </header>
    </div>
  );
}

export default App;
```

{% endcode %}

## Base

Complete High Card with the following features.

1. Determine who has won each round (Player 1 or Player 2)
2. Keep score during each game (how many rounds has each player won)
3. Declare a winner at the end of each game when the deck has run out of cards, and give the players the option to restart the game.

## Comfortable

Add nice-to-have features.

1. Style the app to clarify what each UI component is for. Clarify which card belongs to which player. Consider using [React Bootstrap](https://react-bootstrap.github.io/docs/components/accordion) or [MUI](https://mui.com/core/) components as default styles.
2. Create a re-usable `PlayingCard` component to render cards nicely. This component can use playing card images or create a custom playing card UI.

## More Comfortable

If you have time and want to practise more.

1. Allow players to keep track of scores across games, not just across rounds within a single game.

## Submission

Submit a pull request to the `main` branch of Rocket's High Card repo and share your PR link in your section Slack channel.

If you would like to deploy your app to the internet, follow Vitejs GitHub Pages [deployment instructions here](https://vitejs.dev/guide/static-deploy.html).

## Reference Solution

Here is [reference code](https://github.com/rocketacademy/high-card-3.2/tree/solution-base) and a [reference deployment](https://rocketacademy.github.io/high-card-3.2/) for this exercise. You can do better!


# 1.E.5: Guess The Word

## Learning Objectives

1. How to use forms with React and controlled components
2. Get comfortable applying JS logic in React

## Introduction

Guess The Word (aka Hangman) is a single-player game where a user tries to guess all letters in a secret word with a limited number of guesses. Correct guesses will reveal the instances of the guessed letter in the word. Incorrect guesses will reduce "guesses remaining". A user wins when they guess all letters in the word correctly, and loses when there are no guesses remaining.

## Starter Code

Fork and clone [Rocket's Guess The Word repo](https://github.com/rocketacademy/guess-the-word-3.2) (Rocket-themed React ViteJs Application). Understand the following starter code in `App.jsx` before creating GTW, and feel free to change anything you would like in `App.jsx`. Run `npm install` to install packages and `npm run dev` to start the app, next open your browser and navigate to [http://localhost:5173](http://localhost:5173/).

{% code title="App.jsx" lineNumbers="true" %}

```jsx
import logo from "/logo.png";
import "./App.css";
import { getRandomWord } from "./utils";
import { useState } from "react";

function App() {
  // currWord is the current secret word for this round. Update this with the updater function after each round.
  const [currWord, setCurrentWord] = useState(getRandomWord());
  // guessedLetters stores all letters a user has guessed so far
  const [guessedLetters, setGuessedLetters] = useState([]);

  // Add additional states below as required.

  const generateWordDisplay = () => {
    const wordDisplay = [];
    // for...of is a string and array iterator that does not use index
    for (let letter of currWord) {
      if (guessedLetters.includes(letter)) {
        wordDisplay.push(letter);
      } else {
        wordDisplay.push("_");
      }
    }
    return wordDisplay.toString();
  };

  // create additional function to power the

  return (
    <>
      <div>
        <img src={logo} className="logo" alt="Rocket logo" />
      </div>
      <div className="card">
        <h1>Guess The Word 🚀</h1>
        <h3>Word Display</h3>
        {generateWordDisplay()}
        <h3>Guessed Letters</h3>
        { guessedLetters.length > 0 ? guessedLetters.toString(): "-"}
        <br />
        <h3>Input</h3>
        {/* Insert form element here */}
      </div>
    </>
  );
}

export default App;
```

{% endcode %}

## Base

Add a form HTML element in `App.jsx` as per what we learned in [React Forms](/1-frontend/1.3-react#9-forms-input-select-textarea) to allow the user to input guesses. Each guess can only consist of 1 letter at a time. Control form input using component state as per the React Guide.

When the user guesses a letter, add that letter to the `App` component's `guessedLetters` state. Consider using the [spread operator](/0-foundations/0.4-javascript/0.4.5-destructuring-and-spread-operator#spread-operator) when adding the new letter to trigger React to re-render. The existing starter code logic will read `guessedLetters` and render correctly-guessed letters in the Word Display section and render all guessed letters in the Guessed Letters section.

Add logic and state to track whether the user has guessed all letters of the word and how many guesses the user has left (can start with 10). If the user guesses all letters correctly, tell them they have won. If the user runs out of guesses, reveal the word and tell them they have lost. When the round ends, give the user an option to play again.

{% hint style="info" %}
**Hard-code secret word for easier testing**

When testing your app, you may find it easier to hard-code the secret word initialised in state. Guessing words is hard!
{% endhint %}

## Comfortable

Style the app to clarify what each UI component is for. Create an image that appears gradually with every wrong guess for the user to visualise how many guesses they have left. Consider using [React Bootstrap](https://react-bootstrap.github.io/components/alerts) or [MUI](https://mui.com/core/) components as default styles.

## More Comfortable

Allow the user to play multiple rounds and display their score across rounds, e.g. how many times they have guessed the word out of how many rounds.

## Submission

Submit a pull request to the `main` branch of Rocket's High Card repo and share your PR link in your section Slack channel.

If you would like to deploy your app to the internet, follow Vitejs GitHub Pages [deployment instructions here](https://vitejs.dev/guide/static-deploy.html).

## Reference Solution

Here is [reference code](https://github.com/rocketacademy/guess-the-word-3.2/tree/solution-base/src) and a [reference deployment](https://rocketacademy.github.io/guess-the-word-3.2/) for this exercise. You can do better!


# 1.P: Frontend App

## Introduction

Build an Application that solves a problem you have using React, HTML and CSS. We will not be able to persist data in database until Module 2, but there are still many useful apps we can build. If you want to try to create an Application with a rudimentary database please look at HTML's [localStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) where we can manage JSON within our React Application.&#x20;

## Requirements

### App Stack

This project must be a Frontend React Application that utilises React, HTML and CSS.

### User Interface

* [ ] The user interface of the Application is consistently styled across all components and screens
* [ ] The Application is intuitive, usable and easy to navigate
* [ ] Application has been styled with superb custom CSS, [React Bootstrap](https://react-bootstrap.github.io/components/alerts), [MUI](https://mui.com/core/) or another component UI or CSS framework

### Functionality&#x20;

* [ ] The core functionalities of the application work as intended and expected
* [ ] The Application handles props effectively across components
* [ ] The Application manages and updates state effectively
* [ ] Interactivity:
  * [ ] The Application contains at least 1 input that captures user input to alter Application state&#x20;
  * [ ] The Application contains at least 1 call to action that alters Applications state
  * [ ] The Application can reflected updated state in the UI
* [ ] Complexity:
  * [ ] Application has at least 2 levels of components eg: \
    App component and 1 or more child components
  * [ ] Application demonstrates the capability to lift up state

### Code Quality

* [ ] Application is organised as well as structured, it follows practices of component separation and has a good folder structure
* [ ] The code is easy to comprehend and read
* [ ] The Application contains meaningful variable and function names
* [ ] Application contains components that can be reused
* [ ] The Application preforms well without unwarranted rendering
* [ ] The Application's code follows consistent coding conventions, regarding indentations and formatting
* [ ] The Application follows the correct naming, casing and commenting [best practices](/general-reference/naming-casing-and-commenting-conventions)

### Project Management&#x20;

* [ ] Application has been deployed with [GitHub Pages](https://create-react-app.dev/docs/deployment/#github-pages)
* [ ] Git repository contains commits for each feature with descriptive commit messages
* [ ] Application contains a README with the applications description, user stories and low-fidelity wireframes
* [ ] The README contains instructions on how to run the Application&#x20;

## Ideas

The best ideas are ones that solve our own problems. Since we cannot persist data until Module 2, consider apps that do not require us to store data beyond the current session. For example: games, calculators, guitar tuners, colour matchers, visualisers. Games may be the most engaging to implement because they typically require more logic. Consult your section leader if you are struggling to decide on an idea.

## Timeline

You will have roughly 4 course days to implement and complete this project. We will observe the following timeline to keep us on track.

| Project Day | Checkpoint                                                                                                                                                                                                                 | Feedback                                                                                                                  |
| :---------: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
|      1      | <p><strong>Ideation phase 1</strong></p><p>Post project ideas in Slack for feedback</p>                                                                                                                                    | SL to review ideas and share feedback                                                                                     |
|      2      | <p><strong>Ideation phase 2</strong><br>Create planning docs: user stories, wireframes, kanban board</p>                                                                                                                   | SL to review planning docs and share feedback                                                                             |
|      3      | **Start implementation**                                                                                                                                                                                                   | -                                                                                                                         |
|      4      | -                                                                                                                                                                                                                          | -                                                                                                                         |
|      5      | <p><strong>MVP deadline</strong><br>Users can complete the primary user story</p>                                                                                                                                          | SL to review code in GitHub, share feedback                                                                               |
|      6      | <p><strong>Feature freeze</strong></p><p>No new features, focus on polishing existing features and code to be presentable</p>                                                                                              | SL to review progress and share post-feature-freeze suggestions                                                           |
|      7      | <p><strong>Project presentations</strong></p><p>Practise <a href="/pages/vnQ0MkMbmPv2pn2pzRko#presentations">explaining your work</a> to others. Other batches will join and we will celebrate each others' hard work.</p> | SL to review code in GitHub, share feedback in 30-minute [post-mortem meeting](/logistics/course-methodology#post-mortem) |
|      8      | <p><strong>Demo video</strong><br>Record a <a href="/pages/vnQ0MkMbmPv2pn2pzRko#demo-video">demo video</a> for employers and the public, embed in README</p>                                                               | -                                                                                                                         |

## Project Management Suggestions

Rocket recommends the following project management strategies and tools for all projects.

### User Stories

Start with user stories. Who is our user and what is their [job to be done](https://hbr.org/2016/09/know-your-customers-jobs-to-be-done)? Be as specific as possible. After we articulate user stories we can proceed to design our app.

Example user stories for Project 1:

* An interior designer wants to determine whether 2 or more colours match and what an optimal colour palette might be for given a base colour
* A daily commuter wishes to play Flappy Bird during his 30-minute commute
* A couple wishes to play a game of checkers against each other on their shared computer

Above user stories may not require persisting user data beyond the current session. From Project 2 onward we will learn how to persist user data for multiple users accessing our apps at multiple times on different devices.

### Wireframes

After user stories, create simple wireframes to visually describe how users accomplish user stories with our app. Connect wireframes to form [user flows](https://careerfoundry.com/en/blog/ux-design/what-are-user-flows/) for each user story. Only include what is needed to accomplish user stories, no more and no less. Rocket recommends [Figma](https://www.figma.com), a relatively simple and popular design tool.

[Here](https://www.figma.com/blog/how-to-wireframe/) is an introduction to wireframing with Figma. Rocket recommends only low-fidelity wireframes for our projects due to limited time. Below are example wireframes by Figma; we can create user flows by navigating to the Prototype tab in the right sidebar and adding connections between wireframes.

{% embed url="<https://www.figma.com/file/NkdUszMYMFqhMX31HGUH0o/Wireframing-in-Figma?node-id=0%3A1>" %}
Example wireframes by Figma
{% endembed %}

### Kanban Board

After user stories and wireframes, Rocket recommends using a [kanban board](https://blog.trello.com/kanban-data-nave) to track implementation progress. A kanban board is a progress-tracking board that contains broadly 3 lists of tasks: To Do, Doing and Done. Rocket recommends [Trello](https://trello.com) for its simplicity, and the [Trello Engineering Kanban Template](https://trello.com/templates/engineering/kanban-template-LGHXvZNL) for its relevance to SWE.

Each task on your board should take no more than 1 day to complete. If you think it will take longer than 1 day, break it down into smaller tasks. This will help you stay motivated and track progress more accurately. Move in-progress tasks to the Doing lists and completed tasks to Done.

## Setup

Start by forking [Rocket's Bootcamp Project 1 repo](https://github.com/rocketacademy/project1-3.2) that contains an empty Vitejs app. This will make it easier for SLs to review your code by allowing us to submit projects via pull requests.

## Deployment

If you would like to deploy your app to the internet, follow Vitejs GitHub Pages [deployment instructions here](https://vitejs.dev/guide/static-deploy.html) this should be familiar as we are already using GitHub for code hosting.

## Submission

1. Submit a pull request to Rocket's Project 1 repo
2. Add your Project 1 repo link to the Rocket Bootcamp Projects spreadsheet in your batch-specific sheet shared by your SL.&#x20;

## General Tips

### Mobile First

Rocket recommends designing and building the mobile version of your project before the desktop version. It will be easier to add features to a UI for the desktop version than to remove features from a UI for the mobile version. Use Chrome DevTools to [simulate smaller devices in Chrome](https://developer.chrome.com/docs/devtools/device-mode/).

### Polish

Leave sufficient time to polish your app to be presentable. Fewer, more-polished features are generally better than more, less-polished features. Below is a sample checklist to run through.

1. Are there obvious bugs?
2. Are variable names concise and precise?
3. Do we have [JSDoc comments](https://jsdoc.app/about-getting-started.html#adding-documentation-comments-to-your-code) above major functions and inline comments above code that could be confusing to others?
4. Is each function sufficiently small and modular to be easily readable?
5. Is the visual design clean?
6. Is the app layout responsive?
7. Did we update the app favicon and page title?
8. Did we populate the README?


# 2: Full Stack

## Learning Objectives

1. Learn how the internet works
2. Learn how to use React with Firebase to build apps that persist data and authenticate users
3. Learn how to use React Hooks, React Router, and AJAX requests to build modern React apps with rich functionality and connectivity to 3rd-party APIs
4. Become more confident in reading documentation to learn new technologies

## Introduction

Welcome to full-stack engineering where apps have both a frontend and backend. We will strengthen our foundation in React by learning advanced React techniques such as Hooks, React Router and AJAX requests in React. We will learn to use a backend service Firebase to persist data from our apps and authenticate our users. Module 2 culminates in Project 2 where we will build a fully-featured app that can mimic virtually any app on the market today.


# 2.1: Internet 101

## Learning Objectives

1. The internet is wires that connect computers
2. The internet uses protocols such as HTTP to transmit data reliably
3. DNS translates human-readable URLs to IP addresses that identify computers on the network

## Introduction

![Global map of submarine internet cables. Source: Ars Technica](/files/CyHoEFnoTiKEPgWZ1ERY)

The internet consists of computers, wires and software that sends data between computers through wires.

Internet pioneers developed software protocols that allow us to transmit data across the internet reliably. [Internet governing bodies](https://www.ietf.org/) are continuously upgrading these protocols.

As app developers we do not need to understand these protocols in depth. This page runs through the most important aspects of internet protocols we need to build apps effectively.

## HTTP

[HTTP](https://developer.mozilla.org/en-US/docs/Web/HTTP/Overview) (Hypertext Transfer Protocol) is the most common internet data-transfer protocol. We will use it to send data between our app frontends and backends, as well as between our apps and any 3rd-party [API](https://www.mulesoft.com/resources/api/what-is-an-api#:~:text=API%20is%20the%20acronym%20for,you're%20using%20an%20API.) (Application Programming Interface) services to store or retrieve data.

HTTP consists of "requests" and "responses". Frontends (e.g. browsers, mobile apps, aka "clients") typically send "requests" to backends (aka "servers") to create, retrieve, update or delete data from a database. Backends send back "responses" with confirmations and relevant data.

## Internet Addressing

### URLs

URLs (Uniform Resource Locators) are internet addresses. We will send HTTP requests with URLs to retrieve our frontends and communicate with our backends and 3rd-party APIs.

![A URL consists of these key components. Source: Rocket Academy](/files/3YZlgDATd0i3ZtcqbDQm)

We use ports to identify requests and responses to different applications on the same computer. We can omit ports in URLs when our applications use default ports (e.g. 443 for HTTPS requests, 80 for HTTP).

### IP Addresses

URLs map to IP (Internet Protocol) addresses that identify individual or networks of computers on the internet. IP addresses are network-based, not computer-based, so if we connect our computer to a different network it will have a different IP address.

IP addresses typically consist of 4 numbers from 0-255 separated by `.`, for example `192.158.1.38`. These are known as "[IPv4](https://en.wikipedia.org/wiki/IPv4)" addresses and route most internet traffic today. The world is running out of IPv4 addresses and plans to transition to "[IPv6](https://en.wikipedia.org/wiki/IPv6_address)" in the coming decades.

### DNS

[DNS](https://www.cloudflare.com/en-gb/learning/dns/what-is-dns/) (Domain Name System) translates domain names in URLs to IP addresses so our requests can reach the right servers. It's helpful to have domain names decoupled from IP addresses so we can change servers without changing domain names.&#x20;

When we rent or buy a domain name and want to host our website or server there, we will need to add 1 or more "DNS records" to our domain to let DNS know where to find our server.


# 2.1.1: Chrome DevTools Network Panel

## Learning Objectives

1. Know how to inspect network requests and responses in Chrome

## Introduction

Chrome and other modern browsers provide convenient functionality for analysing network requests and responses. This will help us debug our apps when our frontends do not receive the data we expect from our backends.

## Usage

[Open Chrome DevTools](https://developer.chrome.com/docs/devtools/open/). The following image shows the DevTools Network panel after we send a request to `google.com`. Notice there are many more requests than the initial `google.com` request. These secondary requests are typically for scripts, images and other resources the page needs to function.

![The Network panel shows a list of requests from this browser in increasing chronological order. Source: Rocket Academy](/files/q7Ib7JIuUS4jEK1mDjQ3)

Click on an individual request to inspect its details. The Headers tab shows important request and response headers such as URL, HTTP method and response status code. The Response tab shows response data. Both are helpful in determining whether a bug is in our frontend or backend logic.

![Clicking on an individual request shows us that request's details. Source: Rocket Academy](/files/XjZWF5rpZpLPA2YKaubq)

## Disable Cache

Rocket recommends [disabling Chrome's cache when DevTools is open](https://stackoverflow.com/a/7000899) to avoid situations when our apps do not reflect recent code changes due to caching. We recommend keeping this checkbox checked permanently to save us time during development.


# 2.1.2: HTTP Requests and Responses

## Learning Objectives

1. HTTP requests are instructions to manage data on a remote server; HTTP responses are acknowledgments from the server
2. What to pay attention to in HTTP requests and responses
3. How to send HTTP requests via JavaScript and Thunder Client

## Introduction

HTTP "requests" are instructions sent over the internet to create, retrieve, update or delete data. HTTP "responses" are acknowledgments of HTTP requests, containing information describing the status of the request and containing any relevant data. Libraries like Firebase wrap HTTP requests and responses in their library functions, but most data sources do not have libraries like Firebase and we will need to explicitly send HTTP requests to access those data sources.

We must assume it will take an indefinite amount of time to receive a response for an HTTP request, and use JavaScript promises or callbacks (promises preferred) to write logic that is dependent on the response. This is because our requests often must literally travel across the world and internet connectivity can be unstable.

## Important HTTP request and response headers

HTTP request and response headers are key-value pairs that store metadata for requests and responses. There are many kinds of request and response headers, and for our purposes we will pay attention to the request method and status code headers.

### Request Method

The [request "method"](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods) communicates the kind of action we are requesting. The 4 most common methods are GET, POST, PUT, and DELETE, of which GET and POST are the most common.&#x20;

| Method | Purpose       | Notes                                                                                                 |
| ------ | ------------- | ----------------------------------------------------------------------------------------------------- |
| GET    | Retrieve data | GET is default and most common method. We trigger GET requests when we enter URLs in the browser bar. |
| POST   | Create data   | POST requests store data in the request "body", part of the request that is separate from headers     |
| PUT    | Update data   | Similar mechanics as POST but with different name for clear communication                             |
| DELETE | Delete data   | Similar mechanics as POST but with different name for clear communication                             |

### Response Status Code

The [response "status code"](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status) is a number that communicates the status of the request. Statuses can communicate success, failure and what kind of failure it was. Below are common status codes.

| Status Code | Meaning   | Notes                                                                |
| ----------- | --------- | -------------------------------------------------------------------- |
| 200         | OK        | 200 is the most common status code, and it generally means "success" |
| 404         | Not Found | Visited page that does not exist                                     |
| 403         | Forbidden | We do not have access to retrieve this resource                      |

Software engineers decide what status code to attach to each response in app logic. We will do this when we write our own backend servers in Module 3. When sending responses, we should strive to provide the most precise status code for the given request. [This page](https://www.restapitutorial.com/httpstatuscodes.html) summarises HTTP status codes and what they represent.

## How to send requests

Our apps need to send HTTP requests to access data from external sources. We will learn to send HTTP requests programmatically using JavaScript (for our users) and a VS Code extension called [Thunder Client](https://www.thunderclient.com/) (for us to test APIs independently from our frontends). Note we have already been sending requests with Chrome (by visiting websites).&#x20;

### JavaScript

Rocket recommends using the NPM library [Axios](https://axios-http.com/docs/intro) to send HTTP requests from our apps. Axios is the most robust and popular JavaScript request-sending library we are aware of.&#x20;

Below is an example Axios request from their [official docs](https://axios-http.com/docs/example) that gets user data from the user with ID "12345". To use Axios we must install it as an [NPM package](https://www.npmjs.com/package/axios) and import it in the relevant file with `import axios from "axios"`.

```javascript
// Make a request for a user with a given ID
axios.get('/user?ID=12345')
  .then(function (response) {
    // handle success
    console.log(response);
  })
  .catch(function (error) {
    // handle error
    console.log(error);
  })
```

### Thunder Client

[Thunder Client](https://www.thunderclient.io/) (TC) is a VS Code Extension that enables us to send requests and receive responses without our app frontends. This is helpful for testing APIs to determine if a bug is in the API or in our frontend.

TC provides a convenient interface for creating and populating request URLs, methods, bodies, and query parameters. After sending requests with TC, TC formats responses for us in the VS Code interface.

![Thunder Client provides a convenient interface for testing APIs. Source: Thunder Client](/files/FgfJ0rizXByNtYG8oWFx)

There are many alternatives to Thunder Client, among which is a popular software called [Postman](https://www.postman.com/). Rocket chose Thunder Client because of its simplicity and integration with VS Code.


# 2.2: Advanced React

## Learning Objectives

1. Learn how to use React Hooks syntax
2. Learn how to use React Router
3. Learn how to use higher-order components
4. Learn how to use React context


# 2.2.1: AJAX

## Learning Objectives

1. AJAX means asynchronous HTTP requests in JavaScript that can update UI without refreshing the page
2. We can send arbitrary HTTP requests from any React component to send and retrieve data from external APIs
3. Understand how to send HTTP requests from React components and where to send them

## Introduction

AJAX (Asynchronous JavaScript and XML) is a technique for sending asynchronous HTTP requests in JavaScript that can update UI without refreshing the page. XML is an older markup language for sending and receiving data that is now less commonly used than JSON, but the software community continues to use the abbreviation AJAX out of convention.

## AJAX in React

[React's official docs](https://reactjs.org/docs/faq-ajax.html) provide clear examples of how to make AJAX requests from both class and Hook-based React components on component load.

{% embed url="<https://reactjs.org/docs/faq-ajax.html>" %}

1. The examples use the [Fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) AJAX library, but we will use [Axios](https://axios-http.com/docs/intro) at Rocket because Axios is the most robust and popular as far as we know
2. The examples fetch first-load data in `componentDidMount` or `useEffect` instead of directly in the functional component to avoid fetching data every time the component re-renders
3. `res.json()` extracts the JSON object out of the response. `result` in the subsequent callback contains that object.
4. The examples show how to send AJAX requests to populate data in components on component load, but not how to send requests on a user action such as a button click (e.g. like button). For the latter we can safely define a callback method in our component (e.g. `handleClick`) that performs a request on button click without worrying about fetching data more times than necessary.


# 2.2.2: React Router

## Learning Objectives

1. React Router allows us to keep our app URLs in sync with components we are viewing.
2. How implement React Router in our applications.
3. How to control user flow with React Router.
4. How to implement Private Routing within our applications.

## Introduction

React Router DOM is a React library that enables us to keep our app URLs in sync with Components that are rendered in the browser. Prior to React Router DOM we needed to extensively add supplementary code to our app so that our URL did update, which is fine for small single-page apps but less so when our apps gets more complex with many pages and different URL endpoints.

Scroll through the [React Router DOM homepage](https://reactrouter.com/) to become familiar with the implementation concepts that are used by this package. The implementations that follow aim to give you an understanding of the routing system in React Router DOM quickly and without fuss.

## Official Tutorial

Complete the official React Router DOM tutorial to familiarise yourself with React Router. Once we learn the mechanics of React Router we will integrate it into our React ViteJs apps.

{% embed url="<https://reactrouter.com/en/main/start/overview>" %}
React Router&#x20;
{% endembed %}

1. React Router can be implemented in a variety of ways, we will be show casing the use of [createBrowserRouter](https://reactrouter.com/en/main/routers/create-browser-router) and [createRoutesFromElements](https://reactrouter.com/en/main/utils/create-routes-from-elements) in the code samples below to implement the router system.&#x20;
2. Pay attention to how we can implement nested `Route`s within the router system.
3. Pay attention to how the `Outlet` component renders out sub components within the nested router system.
4. Always add an ErrorElement within the router system in our apps for robustness and to help redirect users to a useful page.
5. Note we need to import the React Router React Hook `useParams` from `react-router-dom` to get URL params when to use within our router system.

### Vital Imports&#x20;

[createBrowserRouter](https://reactrouter.com/en/main/routers/create-browser-router) This function is used to create a router system, it uses the DOM History Api in order to update the URL and manage the applications history. To use this function pass in an array of objects that represent each endpoint within your web application and the desired Component that you want to render. It should be noted that using this function unlocks the use of 'loaders', 'actions' and 'fetchers' that can be added into more complex implementations of React Router.&#x20;

[createRoutesFromElements](https://reactrouter.com/en/main/utils/create-routes-from-elements) This is a utility function that creates route objects out of [Route](https://reactrouter.com/en/main/route/route) elements. This can help with readability when developing your router system, this makes the React Router system appear as JSX as opposed to objects.

[RouterProvider](https://reactrouter.com/en/main/routers/router-provider) All router objects are passed into this Component to render your application within the browser, not that you need to pass all route objects or `Route`'s into the provider otherwise the application will not be able to handle the route.&#x20;

[Route](https://reactrouter.com/en/main/route/route) this Components is used to define the Component or Components that will render depending on the current url path that is in the browser. We utilise Route nesting to develop our complex application layouts as well as data dependencies. `Route`'s contain a 'path' prop that will render the Component onto the screen if the current url matches the 'path' property. The other vital prop on a Route is the 'element' prop that signifies the JSX or Component that is to be rendered. If an `Outlet` is contained in these Components, nested `Route` Components may also be rendered onto the screen, depending on the URL.

[Outlet](https://reactrouter.com/en/main/components/outlet) This Component is used so that multiple path Components can be rendered onto the browser. Therefore the use of `Outlet`s faciliate nested routing such that we can view multiple Components.&#x20;

[Link](https://reactrouter.com/en/main/components/link) This component allows our users to navigate through the application such that they can visit every path and therefore every component. The links have a 'to' prop which should match a `Route`'s path prop.&#x20;

### Example Simple Implementation

{% code title="Navbar.jsx" lineNumbers="true" %}

```jsx
import { Link } from "react-router-dom";
function Navbar() {
  return (
    <div className="navbar">
      <Link to="/">Home</Link>
      <Link to="/api">Api</Link>
      <Link to="/profile">Profile</Link>
      <Link to="/component">Component</Link>
    </div>
  );
}
export default Navbar;
```

{% endcode %}

{% code title="App.jsx" lineNumbers="true" %}

```jsx
import Navbar from "./Components/Navbar.jsx";
import "./App.css";

import {
  createBrowserRouter,
  RouterProvider,
} from "react-router-dom";

export default function App() {
  const router = createBrowserRouter([
    {
      path: "/",
      element: (
        <div>
          <Navbar />
          <h1>Hello World</h1>
        </div>
      ),
    },
    {
      path: "api",
      element: (
        <div>
          <Navbar />
          <h1>Hello Api</h1>
        </div>
      ),
    },
    {
      path: "profile",
      element: (
        <div>
          <Navbar />
          <h1>Profile</h1>
        </div>
      ),
    },

    {
      path: "component",
      element: (
        <div>
          <Navbar />
          <h1>Component</h1>
        </div>
      ),
    },
  ]);
  return (
    <>
      <h1>Hello World</h1>
      <RouterProvider router={router} />
    </>
  );
}
```

{% endcode %}

<figure><img src="/files/ZqBU8y0io5O6v5ogc72o" alt=""><figcaption><p>http://localhost:5173/profile</p></figcaption></figure>

The code above will implement a simple form of routing within our a basic React Application, when viewing the application in the browser following the command `npm run dev`, you will be able to access each element that was passed into `createBrowserRouter`, based off the URL endpoint that is visited. Eg: `http://localhost:5173/profile` to render the Profile Component.   As you can see from the code above each object contains a "path" and an "element" key. The element can be a collection of JSX or a React Component, we will explore using Components within the router in the next example. Note that the path value matches a `Link`'s "to" property value that is defined in the file `Navbar.jsx`. This is how routing is set up utilising React Router DOM.

If you would like to checkout the code implementation please checkout [this repository](https://github.com/rocketacademy/react-routing-3.2/tree/simple_example).&#x20;

It should be noted that developers can pass any number of props that are required to React Components within the Application. To showcase this we can use the code sample above, we will pass a prop into the `Navbar` Component. Add a prop to your Components in the conventional fashion, consider the sample below:

```jsx
<Navbar disabled={false} />
```

Note that this is just a sample and is not implemented within the codebase.&#x20;

### Sample Implementation Nested Routes

{% code title="App.jsx" lineNumbers="true" %}

```jsx
import CallApi from "./Components/CallApi.jsx";
import Root from "./Components/Root.jsx";
import Profile from "./Components/Profile.jsx";
import Component from "./Components/Component.jsx";
import ErrorPage from "./Components/ErrorPage.jsx";
import Home from "./Components/Home.jsx";
import "./App.css";

import {
  createBrowserRouter,
  RouterProvider,
} from "react-router-dom";

export default function App() {
  const router = createBrowserRouter([
    {
      path: "/",
      element: <Root />,
      errorElement: <ErrorPage />,
      children: [
        { path: "/", element: <Home /> },
        { path: "api", element: <CallApi /> },
        {
          path: "profile",
          element: <Profile />,
          children: [
            {
              path: "edit",
              element: (
                <div>
                  <h3>Edit Profile</h3>
                  <p>Edit me now</p>
                </div>
              ),
            },

            {
              path: "view",
              element: (
                <div>
                  <h3>View Profile</h3>
                  <p>View me now</p>
                </div>
              ),
            },
          ],
        },
        { path: "component", element: <Component /> },
      ],
    },
  ]);
  return (
    <>
      <h1>Hello World</h1>
      <RouterProvider router={router} />
    </>
  );
}
```

{% endcode %}

In the code sample above there are two nested routes, every Component is nested under the '/' route and there are two nested routes under '/profile'. The first '/' path nests these additional paths, 'api', 'profile', 'component'. While the second nested example '/profile' nests the paths 'edit' and 'view'. This is indicated by the children property in the objects specified above. If an object doesnt contain the children property, it doesn't nest any paths.&#x20;

When developing an application that contains nested routes it should be noted that you will need to use an `Outlet` on the parent Route's in order to render its children based off the visited URL. This can be seen in the case of the `Root` path, with the value of '/'  in this example.&#x20;

Below is the `Root` Component to reduce repetitive code, we have embedded the `Navbar` within the `return` statement before the `Outlet`. Note that this `Outlet` is used to render out the child Components listed within the `App.jsx`, the `Outlet` empowers the routes `'/'`, `'/api'`, `'/profile'`, `'/component'`, as well as `'/error'`, when visited these paths render the `Home`, `CallApi`, `Profile`, `Component` and `ErrorPage` Components respectively. &#x20;

The `Navbar` Component can be found within the example above, `Navbar.jsx`.

{% code title="Root.jsx" lineNumbers="true" %}

```jsx
import { Outlet } from "react-router-dom";
import Navbar from "./Navbar";
export default function Root() {
  return (
    <div>
      <Navbar />
      <Outlet />
    </div>
  );
}
```

{% endcode %}

The `Profile` Component, shown below, also contains an `Outlet` to facilitate the nested routes `'/profile/edit'` and `'/profile/view'`.  These paths render JSX elements as opposed to Components within the example  `App.jsx`. Note how the `Profile` also contains `Link` elements such that the user can navigate to the child components.&#x20;

{% code title="Profile.jsx" lineNumbers="true" %}

```jsx
import { Link, Outlet } from "react-router-dom";
function Profile() {
  return (
    <>
      <div className="navbar">
        <Link to="edit">Edit Profile</Link>
        <Link to="view">View Profile</Link>
      </div>
      <h1>Profile</h1>
      <Outlet />
    </>
  );
}
export default Profile;
```

{% endcode %}

### Userflow

Once you have set up basic routing you will want to consider your user flow and if users should be to pushed to a new page if required or when an action is complete, use the method below to achieve this.&#x20;

[useNavigate](https://reactrouter.com/en/main/hooks/use-navigate) This hook allows us to move our users around our application using React Router. An example of this implementation can be seen within our example.

The `ErrorPage` Component is rendered when a user has navigated to a path that isn't handled in the implemented router system. As indicated by the code below, `useNavigate` has been implemented to help the user, this tool allows us to access and alter current url that the user has visited. In this example the user will be navigated back to the home page when the "Home" button is clicked. Note that we could push the users to any page handled within the React Router system, just pass in the relevant path.&#x20;

{% code title="ErrorPage.jsx" lineNumbers="true" %}

```jsx
import { useNavigate } from "react-router-dom";
function ErrorPage() {
  const navigate = useNavigate();
  return (
    <>
      <h1>This route is not found! Please use the give navigation bars</h1>
      <button onClick={() => navigate("/")}>Home</button>
    </>
  );
}
export default ErrorPage;
```

{% endcode %}

Below are the some example Components that could be used to implement the React Router example above.&#x20;

{% code title="Home.jsx" lineNumbers="true" %}

```jsx
function Home() {
  return (
    <>
      <h1>Welcome back Home</h1>
    </>
  );
}
export default Home;
```

{% endcode %}

{% code title="Component.jsx" lineNumbers="true" %}

```jsx
function Component() {
  return (
    <>
      <h1>Component</h1>
    </>
  );
}
export default Component;
```

{% endcode %}

{% code title="CallApi.jsx" lineNumbers="true" %}

```jsx
import axios from "axios";
import { useState, useEffect } from "react";
import PokeCard from "./PokeCard";

export default function CallApi() {
  const [pokemon, setPokemon] = useState([]);
  const [input, setInput] = useState("");

  useEffect(() => {
    axios.get("https://pokeapi.co/api/v2/pokemon/geodude").then((data) => {
      console.log(data);
      const unpackedData = data.data;
      console.log(unpackedData);
      setPokemon([...pokemon, unpackedData]);
    });
  }, []);

  const handleSubmit = (e) => {
    e.preventDefault();
    axios.get(`https://pokeapi.co/api/v2/pokemon/${input}`).then((data) => {
      let info = data.data;
      setPokemon([...pokemon, info]);
    });
  };

  return (
    <>
      <h1>Pokemon Incoming!</h1>
      <input
        type="text"
        value={input}
        placeholder="Pokemon Name"
        onChange={(e) => setInput(e.target.value)}
      />
      <input type="submit" value="submit" onClick={handleSubmit} />
      {pokemon && pokemon.length > 0 ? (
        pokemon.map((avatar) => (
          <div key={avatar.id}>
            <PokeCard {...avatar} />
          </div>
        ))
      ) : (
        <p>No Pokemon here</p>
      )}
    </>
  );
}
```

{% endcode %}

{% code title="Pokecard.jsx" lineNumbers="true" %}

```jsx
export default function PokeCard(props) {
  return (
    <div className="card">
      <h2>{props.name}</h2>
      <img src={props.sprites.front_default} alt={props.name} />
      <p>{props.weight}</p>
    </div>
  );
}
```

{% endcode %}

<figure><img src="/files/UHkQDm5IMExcZ9v2y5Nq" alt=""><figcaption><p>http://localhost:5173/profile/view</p></figcaption></figure>

This is the output of the current code showcasing the nested route and what it would look like. If you would like to checkout the code implementation please checkout [this repository](https://github.com/rocketacademy/react-routing-3.2/tree/nested_routes).&#x20;

### createRoutesFromElements

While the above implementation works and is able to render out various pages it is possible to make routing easier to read, such that you can easily identify nested routes within your codebase. To do this we would need to convert the objects that were passed in the previous example into `Route` Components, passing any required properties, the key props are "path" and "element".  &#x20;

{% code title="createRoutesFromElements App.jsx" overflow="wrap" lineNumbers="true" %}

```jsx
import CallApi from "./Components/CallApi.jsx";
import Root from "./Components/Root.jsx";
import Profile from "./Components/Profile.jsx";
import Component from "./Components/Component.jsx";
import ErrorPage from "./Components/ErrorPage.jsx";
import Home from "./Components/Home.jsx";
import User from "./Components/User";
import "./App.css";

import {
  createBrowserRouter,
  RouterProvider,
  createRoutesFromElements,
  Route,
} from "react-router-dom";

export default function App() {
  const router = createBrowserRouter(
    createRoutesFromElements(
      <Route path="/" element={<Root />}>
        <Route path="/" element={<Home />} />
        <Route path="/api" element={<CallApi />} />
        <Route
          path="/profile"
          element={<Profile />} >
          <Route
            path="edit"
            element={
              <div>
                <h3>Edit Profile</h3>
                <p>Edit me now</p>
              </div>
            }
          />
          <Route
            path="view"
            element={
              <div>
                <h3>View Profile</h3>
                <p>View me now</p>
              </div>
            }
          />
        </Route>
        <Route path="/component" element={<Component />} />
        <Route path="/user/:username" element={<User />} />
        <Route path="*" element={<ErrorPage />} />
      </Route>
    )
  );

  return (
    <>
      <h1>Hello World</h1>
      <RouterProvider router={router} />
    </>
  );
}
```

{% endcode %}

In the code sample above nested routes become easier to identify compared to the earlier implementation of React Router DOM as `Route` tags wrap around any child 'routes' or 'paths'. This is indicated by the `Route` tag which renders the `Root` Component, it starts on line 20 and encompasses all defined `Route`s and closes on line 48. Another example of this is the `Route` that renders the `Profile` Component, it is defined on line 23 and closes on like 44, encompassing the `Route`s that contain the paths 'edit' and 'view'. By developing an application in this manner it is possible to map out possible pages and understand the routing system that was setup.&#x20;

### Parameters and useParams&#x20;

Notice how we added an additional `Route` in the example above, the `user` route, which renders the `User` Component, note that the path property has been implemented with the `username` parameter. This parameter signifies that the value is whatever is passed within the URL provided the rest of the path matches. EG: "<http://localhost:5173/user/sam>" and  "<http://localhost:5173/user/kai>" render the the same Component but will appear difference every time the url changes. Below is the `User` Component, it displays a welcome message as well as the "username" that is passed into the URL.   We can consider this Component to be dynamic because when you navigate to the page and React Router will process the endpoint value of the URL to alter what is rendered within the browser.  Note that if you are implementing this code, there are no navigation `Link`s to this Component, to visit this Component alter the URL in the browser or generate some `Link`s and add them to the Navbar Component.&#x20;

{% code title="User.jsx" lineNumbers="true" %}

```jsx
import { useParams } from "react-router-dom";

function User() {
  const params = useParams();
  return (
    <>
      <h1>Welcome back {params.username}</h1>
    </>
  );
}

export default User;
```

{% endcode %}

<figure><img src="/files/ZPnRWv7HbaZkW1tEzuWh" alt=""><figcaption><p>http://localhost:5173/user/John</p></figcaption></figure>

If you would like to checkout the code implementation please checkout [this repository](https://github.com/rocketacademy/react-routing-3.2/tree/nested_routes_route). Here is the [deployed link](https://rocketacademy.github.io/react-routing-3.2/).&#x20;

## Private Routing

It should be noted that the section below should only be attempted after authentication has been implemented within an application. Before this you wouldn't be implementing a meaningful authenticated routing system. We will be covering authentication later within this module.&#x20;

When you have achieved authentication within your applications you may desire to create private routes. Private routes are routes whose components are wrapped in authenticating logic, this means that users who are not authenticated are unable to access the URL that they tried to visited and will be redirected to another page within the application.&#x20;

{% code overflow="wrap" lineNumbers="true" %}

```jsx
const RequireAuth = ({ children, redirectTo, user }) => {
  const isAuthenticated = user.uid ? true : false;
  return isAuthenticated ? children : <Navigate to={redirectTo} />;
};

// Within a React functional component, wrapped inside a createBrowserRouter object element
      {  
        path: "profile",
        element: (
          <RequireAuth redirectTo={"/"} user={user}>
            <Profile />
          </RequireAuth>
        ),
        children: [
          {
            path: "edit",
            element: (
              <div>
                <h3>Edit Profile</h3>
                <p>Edit me now</p>
              </div>
            ),
          },

          {
            path: "view",
            element: (
              <div>
                <h3>View Profile</h3>
                <p>View me now</p>
              </div>
            ),
          },
        ],
      },
```

{% endcode %}

The `RequireAuth` function checks to see if the user is authenticated, by validating the existence of a "user.uid", if this uid exists, then, then the Component will proceed to render the appropriate Components, in this case the `Profile`. On the other hand if the uid is return undefined, the user is seen as not logged in and they will be redirected to the '/' path. &#x20;

If you would like to checkout the code implementation please checkout [this repository.](https://github.com/rocketacademy/react-routing-3.2/tree/nested_routes_route_auth)&#x20;


# 2.2.3: useContext

## Learning Objectives

1. React context allows us to access shared state from our components without passing props
2. We should use context sparingly, only for state that would be painful to share through passing props
3. How to use `useContext` to simplify syntax when using context with functional components

## Introduction

React context allows us to share state across our app without passing it as props. This is helpful for apps with many levels of component nesting when we would need to use the same state across multiple components and pass state as props through many levels of components (aka "prop drilling"). The React team recommends we use context sparingly because it makes component reuse more difficult.

> "Context is designed to share data that can be considered “global” for a tree of React components, such as the current authenticated user, theme, or preferred language." - React official docs on context

> "...sometimes the same data needs to be accessible by many components in the tree, and at different nesting levels. Context lets you “broadcast” such data, and changes to it, to all components below. Common examples where using context might be simpler than the alternatives include managing the current locale, theme, or a data cache." - React official docs on context

Please read the following official React guide on context.

{% embed url="<https://react.dev/learn/passing-data-deeply-with-context>" %}
React Context
{% endembed %}

1. Note the [Create Context example](https://react.dev/learn/passing-data-deeply-with-context), at this point the default value is being paseed, in this case 1. It refers to the largest heading level in this example but any value can be passed, even an object.
2. Note the [Use Context example](https://react.dev/learn/passing-data-deeply-with-context), after developing a context you can use the information within by utilising the `useContext` hook. &#x20;
3. Note the [Provide the Context example](https://react.dev/learn/passing-data-deeply-with-context#step-3-provide-the-context), to give Components access to the generated context, you must create a Context Provider to encapsulate all of the Components that require this information.&#x20;
4. Checkout this [full example here](https://react.dev/learn/passing-data-deeply-with-context#context-passes-through-intermediate-components) and breakdown how to implement and use context within a React application to avoid prop drilling and repeatative code.&#x20;

## `useContext`

`useContext` is a React Hook that allows us to retrieve the latest value of the context object passed to it. Rocket recommends using `useContext` for context when using functional components.

Please read the following official React guide on `useContext`.

{% embed url="<https://react.dev/reference/react/useContext>" %}
React useContext Hook
{% endembed %}

1. Besides providing simpler syntax for reading context, `useContext` does not change the use cases for context. The examples from the official guide on context still apply, albeit with different syntax.

### Sample Implementation example (Legacy CRA setup)

{% embed url="<https://youtu.be/bLHAhj_ywW8>" %}
React Hooks useContext
{% endembed %}

Please checkout this [repository](https://github.com/rocketacademy/react-context-3.2/) for an example implementation of React useContext, ensure that you're on the `main` branch if you want to test out the application on your machine you will need to install the dependencies with the command `npm install` after the installation you can then run the application with the command `npm run dev`. Note that the video's code is similar but not the same as the given repository.

Checkout the files `App.jsx`, to see the how to create context using the `createContext` method, implemented on line 20. The user object is also defined in the App.jsx and is passed into the `UserContext.Provider`, this file also showcases how to share this context information by wrapping around the `RouterProvider` so that  all children (wrapped components) can share the user data.&#x20;

Within the `Profile.jsx` we can see how to use the user information that is shared within the Applications context, it is required that you import the UserContext that was defined in the `App.jsx` as well as the `useContext` from React. Then utilise the `useContext` method passing in the requested context, in this case, the `UserContext`. Then you can access the information as your would a JavaScript object inside the Components JSX.&#x20;


# 2.2.4: useReducer

## Learning Objectives

1. React useReducer allows us to managed complex state and state transitions within a React Application
2. useReducer is helpful in larger and more complex applications to help organise and simplify code. It allows us to cleanly separate the how of update logic from the what happened of event handlers.&#x20;
3. Learn how to maintain state logic outside of React components by utilising useReducer within the application.&#x20;

## Introduction

When developing React Applications it is advised to break your application into small reusable chunks named Components, there will come a time when there are many state updates spread across all of these Components and their event handlers. If you find that is difficult to maintain your state across all of these Components it might be a good time to implement useReducer and to extract your updating logic from your functions.

{% embed url="<https://react.dev/learn/extracting-state-logic-into-a-reducer>" %}
React and Reducers
{% endembed %}

Explore the link above for the official React implementation and use of useReducer within a React Application. Before we delve into implementation lets note that a reducers in a React context are just functions that take in the state so far as well as an action to return the next state. This means that they accumulate actions over time and this will alter the state. This removes state and updating logic from React Components and allows developers to maintain this information in the Reducer files.&#x20;

When moving from stateful logic to using reducers, we will need to follow these steps.

1. [Move state updates into dispatcher functions](https://react.dev/learn/extracting-state-logic-into-a-reducer#step-1-move-from-setting-state-to-dispatching-actions), this means that we need to alter the way that our components work, remove all of the logic that update states and use it within dispatcher functions. We dispatch these actions to the reducer to update and alter our state.
2. [Write a reducer function](https://react.dev/learn/extracting-state-logic-into-a-reducer#step-2-write-a-reducer-function), the reducer function will now house all of the state updates within the React application, it takes in two arguments the action object as well as the current state. React will align itself to whatever state is returned from the reducer.&#x20;
3. [Use the reducer from your Components](https://react.dev/learn/extracting-state-logic-into-a-reducer#step-3-use-the-reducer-from-your-component), replace any useState methods with the useReducer  and get the required information for your components.&#x20;
4. While useReducer takes a little more setup than using useState, because you need to write both a reducer function and dispatch actions, the reducer cuts down on code if many event handlers modify state in a similar fashion.

## useReducer

`useReducer` is a React Hook that allows us to add a reducer into your Component. This method allows you to extract state from Components into a single store ultimately improving on readability and code maintenance.

{% embed url="<https://react.dev/reference/react/useReducer>" %}
React useReducer
{% endembed %}

## Sample Implementation useContext and useReducer

Two examples have been provided to showcase the use of `useReducer` within our React components, a Shopping List Application has been developed first by using React state, the second developed using `useReducer`. Checkout both example to understand how you can implement and Reducers within React Applications.&#x20;

[ShoppingList application](https://github.com/rocketacademy/react-reducer-3.2) without using useReducer.

[ShoppingList application](https://github.com/rocketacademy/react-reducer-3.2/tree/reducer) using useReducer.&#x20;

The main difference between these repositories is that the updating that logic has been removed and replaced with reducer actions to maintain state. Checkout the `ShoppingLists.jsx` file within the Reducer folder, within is all of the business logic that will maintain state within the application. When developing much larger projects that contain multiple sets of reducers and contexts, this system of extracting state into reducer files will make maintain state updating logic much more efficient instead of being spread throughout your Components. It should be noted that a new pattern of implementing useContext has been showcased in this example. Instead of implementing all of context code within the `App.jsx` we have extracted it into it own file, `ShoppingListProvider.jsx` within the Provider folder. While this isnt necessary, it allows us to further separate React UI logic from state management.&#x20;

## useContext Challenge

Try this out yourself by trying out the [React official challenge](https://react.dev/learn/extracting-state-logic-into-a-reducer#challenges).


# 2.2.5: Environmental Variables

## Learning Objectives

1. Understand the purpose of the `.env` file and dotenv package
2. Implement the dotenv package in a React Application and store environmental variables
3. Use environmental variables stored in the `.env` file in React
4. Use enviromental variables in the backend - Module 3 onwards

## Introduction

When consuming third party API’s, developing databases and deploying servers you may want to obscure vital and secretive data that is used in your application. Use the NPM package dotenv combined with the `.gitignore` file so that you never push sensitive data online always keep your information safe. Use a `.env` file to hide information such as database credentials, API keys, secrets and even your port number. It is imperative you use a dotenv as your API keys may be paired to a credit card and we want to make sure you are not exposing yourself or your future company to potential risks.&#x20;

> Dotenv is a zero-dependency module that loads environment variables from a `.env` file into [`process.env`](https://nodejs.org/docs/latest/api/process.html#process_process_env). Storing configuration in the environment separate from code is based on [The Twelve-Factor App](http://12factor.net/config) methodology.

## dotenv in React

Usually we would need to install dotenv into our applications, but as we are developing in a React environment we can just create a `.env` file and start putting our credentials in there. This is because react-scripts is able to process .env files whenever you run the command `npm run dev`, which means you will be able to use these hidden credentials in your application, but if you edit it you must completely restart the React App.

If you would like to checkout the documentation further look at this set of [documentation](https://github.com/motdotla/dotenv).&#x20;

Note there are different implementations of dotenv in different environments, in this set of documentation pay attention to the React example.&#x20;

{% embed url="<https://vitejs.dev/guide/env-and-mode.html#env-files>" %}
Vitejs & .env
{% endembed %}

1. You will need to create a `.env` file in the root level of your React project.
2. Store your sensitive data inside the `.env` file.
   1. Note when developing .env files within a React application you must prefix its name with: \
      VITE`_SOME_...`
   2. You will need to reference it with the same prefix: `import.meta.env.VITE_SOME_...`
3. Ignore your .env file within the `.gitignore` file.
4. Create a .env.sample file to indicate what credentials are required in your application.
5. Remember if you alter your .env file you may need to restart React application, stop your server and run `npm run dev`.

   <figure><img src="/files/MyaX1A3b1WzhFmWuxxGR" alt=""><figcaption><p>Sample Folder Structure</p></figcaption></figure>

####

<figure><img src="/files/E5lYknwpdYxQmMsPxiGX" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/L7ZkHwM3nMRQuWmVwzjo" alt=""><figcaption></figcaption></figure>

#### Use cases for the .env?

When developing your applications you might be wondering what information you should share with collaborators and what you should never share. If you are developing an application that consumes or is connected to a third party that requires payments, you will be given keys or secrets to validate your account, this information should be placed in the .env and hidden from everyone but yourself.&#x20;

If a key or secret that is linked to a credit card is accidentally put onto GitHub, this could have dire consequences. When developing with the paid subscriptions of APIS such as [Spoonacular API](https://spoonacular.com/) or even [Google Cloud API](https://console.cloud.google.com/) you will want to hide your API key as if its accidentally put onto GitHub, you could be charged hundreds or even thousands as people steal and use your key to power your own application.  You will then need to generate new keys, remove your application from GitHub and perhaps even stop your credit card.&#x20;

API keys are not the only thing that should be stored in the .env file, database credentials as well as environmental details such as the port number should be safely hidden away. If a malicious developer was afforded the chance they would be able to steal all of the information stored and even delete the data. So save yourself and your potential companies time by securely storing your sensitive data in a .env file.&#x20;

## dotenv and the Backend

When you create your backend using ExpressJs and NPM, you will quickly realise that we don't have the internal React tools that would automatically create the .gitignore and process .env file within your application. To use dotenv within an NPM or backend project we will need to follow the [documentation online](https://www.npmjs.com/package/dotenv). When you use enviromental variables within an Express application you will need to install the package into the npm directory.&#x20;

Run the command&#x20;

```
npm install dotenv
```

After the installation has been completed you can create your .env file within the root of the backend directory.&#x20;

![](/files/alTX4gSIapsv99JRMj4P)

You can create the enviromental variables in the same way that we have developed them for our React applications.

When using the .env to refernce your credentials within your file, you will need to add the highlighted line above any reference. That way your code is able to extract the information required within the .env.

![](/files/juCBmzgyDYQ5otHvRwSE)

It should be noted that like React if you update the dotenv you will need to restart the application.&#x20;


# 2.2.6: React useMemo - useCallback

## Introduction

We’ve talked about `useState` and `useEffect` which is the building block of all React application. You can arguably create any React project with just these two hooks.

As your app scales, you might find that these hooks alone might not be enough to create an *optimised* application because there’ll be lots of state changes and side-effect that will be happening and it might **slow your app down.**

This is why React comes with some built-in hooks to help alleviate this

Here’s a list of additional React hooks from their [documentation](https://reactjs.org/docs/hooks-reference.html#additional-hooks).

Before we dive in, let’s take a look at one of the technique React uses called memoization

### Memoization

So what is memoization?

From wikipedia -

> … **memoization** is an [optimisation](https://en.wikipedia.org/wiki/Optimization_\(computer_science\)) technique used primarily to speed up [computer programs](https://en.wikipedia.org/wiki/Computer_programs) by storing the results of expensive [function calls](https://en.wikipedia.org/wiki/Subroutine) and returning the cached result when the same inputs occur again

The key takeaways are:

* Optimisation technique
* Speed things up
* Returns cache result if input is the same

Let’s take a look at an example of an expensive function call by implementing the Fibonacci number of N sequence

```jsx
function fibonacci(n) {
	  if (n < 2) return 1;
    return fibonacci(n - 1) + fibonacci(n - 2);
}

// What is the "4th" sequence in the Fibonacci's number?
fibonnacci(4)
// Answer: 3

// What is the "20th" sequence in the Fibonacci's number?
fibonnacci(20)
// Answer: 10946

// What is the "50th" sequence in the Fibonacci's number?
fibonnacci(50)
// Answer: uh oh something broke
```

As you can see, if you were to find the “50th” sequence in Fibonacci’s number using the code above, things start to break\*.\* The reason it broke is because our recursive call still calculates the value of the previous functions even when it has calculated it before

* Example of how it looks like

<figure><img src="https://s3.us-west-2.amazonaws.com/secure.notion-static.com/f05e0db7-7b5a-4b48-8300-5b690a4ab776/ezgifcomgifmaker.gif?X-Amz-Algorithm=AWS4-HMAC-SHA256&#x26;X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&#x26;X-Amz-Credential=AKIAT73L2G45EIPT3X45%2F20220916%2Fus-west-2%2Fs3%2Faws4_request&#x26;X-Amz-Date=20220916T010606Z&#x26;X-Amz-Expires=86400&#x26;X-Amz-Signature=e134a9583e4cb652221d986b755b7320f13c44f335d15e328271de78a5bb100c&#x26;X-Amz-SignedHeaders=host&#x26;x-id=GetObject" alt=""><figcaption><p>Gif courtesy of geeksforgeeks <a href="https://www.geeksforgeeks.org/javascript-memoization/#:~:text=Importance">https://www.geeksforgeeks.org/javascript-memoization/#:~:text=Importance</a> of Memoization<br> When you cache an answer from memory.</p></figcaption></figure>

This is where memoization comes in, so let’s optimise it by returning the cache result of our function instead!

```jsx
function memoisedFibonacci(n, cache = []) {
		if (n < 2) return 1;
    if (cache[n]) return cache[n];
    return cache[n] = memoisedFibonacci(n - 1, cache) + 
    memoisedFibonacci(n - 2, cache);
}

// What is the "50th" sequence in the Fibonacci's number?
fibonnacci(50)
// Answer: 20365011074
```

We’ve introduced an additional param to our function called `cache` and set the value of it to be an empty array if it doesn’t exists.

This stores the *previous* value of our result and we send the value to our function so that the program doesn’t need to recompute the value again and again and again and again and again.

**This will lay the foundation of how memoization works**

## React.memo

[React Top-Level API - React](https://reactjs.org/docs/react-api.html#reactmemo)

One of the API that React provides us that helps with performance is `React.memo`

`React.memo` is a higher order component and is used as a performance optimisation by memoizing the result

Take for example a button component below

```jsx
import React, { useState } from 'react';

const Button = (props) => {
  console.log("I am rendering as a button!")
  return (
      <button>{props.children}</button>
  )
}

function App() {
	const [text, setText] = useState('');

	const changeText = (e) => {
		setText(e.target.value);
	};

	return (
		<div className='App'>
			<input type='text' value={text} onChange={changeText} />
			<Button>Submit</Button>
		</div>
	);
}

export default App;
```

When my `App` loads, it will render the `Button` component

Inside my `App`, if a user types in the input, it will call the function `changeText` which will call `setText` and re-render the components

This might seem minor but on a page with many components, we don’t really want a simple `Button` component to re-render every time a user types right?

This is where `React.memo` comes in and is a handy way to optimise unnecessary re-renders

```jsx
import React, { useState } from 'react';

// Wrapping my button component with React.memo
const Button = React.memo((props) => {
  console.log("I am rendering as a button!")
  return (
      <button>{props.children}</button>
  )
})

function App() {
	const [text, setText] = useState('');

	const changeText = (e) => {
		setText(e.target.value);
	};

	return (
		<div className='App'>
			<input type='text' value={text} onChange={changeText} />
			<Button>Submit</Button>
		</div>
	);
}

export default App;
```

By simply wrapping it in `React.memo` whenever state changes in my `App` it will not cause a re-render of the `Button` component! React will skip rendering the component, and reuse the last rendered result.

💡 A good way to know when to use it for a component is if the component renders the same result given the same props.

## useMemo

```jsx
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
```

> Returns a [memoized](https://en.wikipedia.org/wiki/Memoization) value.

This is the equivalent of `React.memo` that we encountered except that it’s for **values.**

Below, we changed the `Button` component to track a `count` state. Every-time we click the button, we will add `1` to `count`. We also implemented the fibonacci sequence from above and plugged it into our `App`

```jsx
import React, { useState } from 'react';

const Button = React.memo((props) => {
	return <button onClick={props.handleOnClick}>{props.children}</button>;
});

function App() {
	const [num, setNum] = useState(0);
	const [count, setCount] = useState(0);

	const handleChangeNum = (e) => {
		setNum(e.target.value);
	};

	const handleCounterClick = (e) => {
		setCount((prevState) => prevState + 1);
	};

	const result = fibonacci(num);

	return (
		<div className='App'>
			<input type='number' value={num} onChange={handleChangeNum} />
			<p>The fibonacci number is {result} </p>
			<p>Counter is {count}</p>
			<Button handleOnClick={handleCounterClick}>Increase the counter!</Button>
		</div>
	);
}

function fibonacci(n) {
	console.log('calculating');
	if (n < 2) return 1;
	return fibonacci(n - 1) + fibonacci(n - 2);
}

export default App;
```

Notice how whenever we clicked on the `Button` component to add to the counter, our whole `App` re-renders again and we will have to recalculate our fibonacci number even though the `num` state didn’t change.

This is an issue especially if the number is big and our function will be really expensive to compute.

Luckily, this is where `useMemo` comes in and optimises the performance by *skipping* the calculation part if the input hasn’t changed! In essence, we *memoized* the result and from `useMemo` and we keep track of the input of `num` in the dependency array.

```jsx
import React, { useState, useMemo } from 'react';

const Button = React.memo((props) => {
	return <button onClick={props.handleOnClick}>{props.children}</button>;
});

function App() {
	const [num, setNum] = useState(0);
	const [count, setCount] = useState(0);

	const handleChangeNum = (e) => {
		setNum(e.target.value);
	};

	const handleCounterClick = (e) => {
		setCount((prevState) => prevState + 1);
	};

	// Wrap the function call in a useMemo hook and put num in the dependency array
	const result = useMemo(() => fibonacci(num), [num]);

	return (
		<div className='App'>
			<input type='number' value={num} onChange={handleChangeNum} />
			<p>The fibonacci number is {result} </p>
			<p>Counter is {count}</p>
			<Button handleOnClick={handleCounterClick}>Increase the counter!</Button>
		</div>
	);
}

function fibonacci(n) {
	console.log('calculating');
	if (n < 2) return 1;
	return fibonacci(n - 1) + fibonacci(n - 2);
}

export default App;
```

## useCallback

If you ran the code above, you’ll actually realise that our previous `Button` component that we wrapped in `React.memo` actually is re-rendering again.

Hmm, but nothing changed right? If you look a little closer, this time we are passing in a prop called `handleOnClick` which takes in a function.

```jsx
<Button handleOnClick={handleCounterClick}>Increase the counter!</Button>
```

Well if you passed in a primitive value such as a `string` or an `integer`, it won’t cause a re-render if the value remained the same, but why did passing in a `function` caused an issue?

The real reason is because functions are compared by reference and not by value. The code below illustrates this example:

```jsx
const funct1 = function() {
  return 20;
};
const funct2 = function() {
  return 20;
};
console.log(funct1 === funct2); // this will be false
```

Whenever React re-renders, the function will be re-generated on every single render, producing a unique function each time. That is to say that the function we passed on to our `Button` component has “changed” on each render, causing it to re-render again!

Fortunately, React has provided us with the `useCallback` hook that will allow us to keep that function that we created to be the same `handleCounterClick` every time.

```jsx
import React, { useState, useMemo, useCallback } from 'react';

const Button = React.memo((props) => {
	console.log('is this rendering?');
	return <button onClick={props.handleOnClick}>{props.children}</button>;
});

function App() {
	const [num, setNum] = useState(0);
	const [count, setCount] = useState(0);

	const handleChangeNum = (e) => {
		setNum(e.target.value);
	};

	// We wrap our function here with the useCallback hook to preserve that reference
	const handleCounterClick = useCallback((e) => {
		setCount((prevState) => prevState + 1);
	}, []);

	const result = useMemo(() => fibonacci(num), [num]);

	return (
		<div className='App'>
			<input type='number' value={num} onChange={handleChangeNum} />
			<p>The fibonacci number is {result} </p>
			<p>Counter is {count}</p>
			<Button handleOnClick={handleCounterClick}>Increase the counter!</Button>
		</div>
	);
}

function fibonacci(n) {
	console.log('calculating');
	if (n < 2) return 1;
	return fibonacci(n - 1) + fibonacci(n - 2);
}

export default App;
```

The `Button` component now will not re-render unnecessarily and we have optimised our `App` to be more performant.

## Conclusion

Despite learning how to make our app more performant, it’s not always necessary to use these hooks. Remember that they are there as tools to help when things feel sluggish or slow. React is a very powerful library that knows how to optimise itself even without using the hooks that we have learned.

Here’s a great article on when you should use the hooks that we have learned by Kent C. Dodds

[When to useMemo and useCallback](https://kentcdodds.com/blog/usememo-and-usecallback)

## Resources

If Here’s a really great resource by Josh W Comeau that takes deep dive into what we just went through.

[Understanding useMemo and useCallback](https://www.joshwcomeau.com/react/usememo-and-usecallback/)


# 2.3: Firebase

## Learning Objectives

1. Firebase allows us to have a backend (e.g. database, authentication) without creating and deploying a dedicated server
2. Firebase helps us build app prototypes faster


# 2.3.1: Firebase Realtime Database

## Learning Objectives

1. Firebase Realtime Database is a NoSQL database that allows real-time data syncing across client applications without the need for a backend
2. How to set up Firebase Realtime Database with React Apps powered by Vitejs

### Introduction

{% embed url="<https://youtu.be/U5aeM5dvUpA>" %}
Firebase Realtime Database is a convenient tool to develop app prototypes. Source: Firebase
{% endembed %}

[Firebase Realtime Database](https://firebase.google.com/docs/database) is a "NoSQL" (i.e. non-relational) JSON database that allows us to persist app data with API calls and sync that data in real-time across multiple app instances (e.g. multiple users). Realtime Database is Firebase's first product and one of their most popular.

Start by reading the following official Firebase Realtime Database tutorials linked below. We will skip the Get Started page and come back to it when working on our first exercise.

### [Structure your Database](https://firebase.google.com/docs/database/web/structure-data)

Read the following Firebase official tutorial on how to structure data in Realtime Database.

1. We can think of JSON objects as JavaScript objects
2. We will learn SQL when we learn about backend
3. We will follow the structure of data in this example to build chat functionality in this module's exercises

### [Read and Write Data on the web](https://firebase.google.com/docs/database/web/read-and-write)

Read the following tutorial on how to read and write data to Firebase Realtime Database. Try to understand the code in each example. We will understand it in more detail when we work on this module's exercises.

1. Skip the "(Optional) Prototype and test with Firebase Local Emulator Suite" section. We can use this later when we need it.
2. We will be using the functions mentioned in the docs to write, read, update and delete data.
3. We may use `off()` to detach listeners when our React components unmount; no need to pay too much attention to this for now.
4. We can ignore "Save data as transactions" section for now. We can revisit this when we need this functionality.

### [Work with Lists of Data](https://firebase.google.com/docs/database/web/lists-of-data)

Read the following tutorial on how to read to, write to, sort and filter lists in Realtime Database.

1. We will use functionality from both "Reading and writing lists" section and "Sorting and filtering data" section in our apps.

### Sample Implementation Legacy (Class Based)

{% embed url="<https://youtu.be/ffj53HLE4Yk>" %}
What is Firebase
{% endembed %}

{% embed url="<https://youtu.be/-xa1ec52y5Q>" %}
Firebase Realtime Database
{% endembed %}

{% embed url="<https://youtu.be/GbsWh2Dif_M>" %}
Firebase Realtime Database Setting Data
{% endembed %}

{% embed url="<https://youtu.be/p3OSy0oOlXE>" %}
Firebase Realtime Database Using Data
{% endembed %}

Please checkout the finished code in this [repository](https://github.com/rocketacademy/firebase-examples-3.2), ensure that you're on the `realtimedatabase` branch. If you want to test out the application on your machine you will need to have registered an Application on Firebase with Realtime Database activated. Use the `sample.env` within the application to create an `.env` file with your Firebase credentials. With this in mind if you want to run the application on your machine you will need to install the dependencies with the command `npm install` after the installation you can then run the application with the command `npm run dev`. Then open a browser of your choice and navigate to  <http://localhost:5173>.


# 2.3.2: Firebase Storage

## Learning Objectives

1. Firebase Storage allows us to store and retrieve user-generated files on the cloud
2. How to set up and use Firebase Storage with a React app

### Introduction

{% embed url="<https://youtu.be/_tyjqozrEPY>" %}
Firebase Storage is a convenient tool to store and retrieve user-generated files. Source: Firebase
{% endembed %}

[Firebase Storage](https://firebase.google.com/docs/storage) is a cloud file storage system that allows us to store and retrieve user-generated files on behalf of our app's users. It allows us to upload user-generated files to Firebase with API calls directly from our frontends and save the locations of those files in our database for easy retrieval.

Start by reading the official Firebase Storage tutorials linked below. We will skip the Get Started page and come back to it when working on the relevant exercise.

### [Create a Reference](https://firebase.google.com/docs/storage/web/create-reference)

1. Note how `ref` syntax is the same as with Realtime Database, but our files are stored in Firebase Storage, not Realtime Database.

### [Upload Files](https://firebase.google.com/docs/storage/web/upload-files)

1. `uploadBytes` makes uploading files easy. We will see how uploading files becomes more complex when using our own backend in Module 3.
2. Note that `uploadBytes` returns a JS promise because we cannot be sure how long it will take for a file to finish uploading. Firebase examples use `.then` syntax to perform logic after promises resolve.
3. Rocket does not require we implement features to show upload progress to users, but that would be a nice touch for Comfortable exercises.
4. `getDownloadURL` function returns a JS promise that resolves to a URL for us to download the file we just uploaded. We will save each file's download URL to our database.

### [Download Files](https://firebase.google.com/docs/storage/web/download-files)

1. No need to worry about CORS Configuration for now unless we plan to have our users download files to their local drives from the browser

### [Delete Files](https://firebase.google.com/docs/storage/web/delete-files)

1. Rocket recommends waiting until the promise returned by `deleteObject` (and any other file upload/download/modifying functions) resolves before updating local state and UI.

### [List Files](https://firebase.google.com/docs/storage/web/list-files)

1. We will most likely not be using `list` and `listAll` functions to retrieve files in our apps, because we will save each file's download URL in our database and retrieve those URLs when loading those files in our apps.
2. No need to implement pagination when using Firebase Storage for the first time. We can implement it as a Comfortable exercise.

### [Handle Errors](https://firebase.google.com/docs/storage/web/handle-errors)

1. If we happen to get a Firebase Storage error we can check the error code in the error object in the promise `.catch` block to verify what happened.

### Sample Implementation Legacy (Class based)

{% embed url="<https://youtu.be/N66Y_Y6sCHc>" %}
Firebase Storage Storing files
{% endembed %}

Note there has been a slight change within React, at minute 6:22, there should be a code alteration, line 76, the new value should be `e.target.value` , and not 'e.target.file'. Please make this amendment if you are following this video!

{% embed url="<https://youtu.be/ztdboeP9Hhw>" %}
Firebase Storage Displaying files
{% endembed %}

Please checkout the finished code in this [repository](https://github.com/rocketacademy/firebase-examples-3.2/tree/storage), ensure that you're on the `storage` branch. If you want to test out the application on your machine you will need to have registered an Application on Firebase with Realtime Database and Storage activated. Use the `sample.env` within the application to create an `.env` file with your Firebase credentials. With this in mind if you want to run the application on your machine you will need to install the dependencies with the command `npm install` after the installation you can then run the application with the command `npm run dev`.  Then open a browser of your choice and navigate to  <http://localhost:5173>.


# 2.3.3: Firebase Authentication

## Learning Objectives

1. Firebase Authentication allows us to authenticate our users with API calls instead of custom password-hashing or OAuth logic
2. How to set up Firebase Authentication with React

### Introduction

{% embed url="<https://youtu.be/8sGY55yxicA>" %}
Firebase Authentication is a plug-and-play authentication solution for our apps. Source: Firebase
{% endembed %}

[Firebase Authentication](https://firebase.google.com/docs/auth) allows us to authenticate our apps' users, manage their accounts in the Firebase console and easily access user auth information from within our application. It makes authentication easy so we can focus on our app logic.

Start by reading the official Firebase Authentication tutorials linked below. Skip "Sign in with a pre-built UI" and "Get Started"; we will not use the former because it is currently incompatible with React 18, and we will go through the latter in the upcoming exercise.

### [Users in Firebase Projects](https://firebase.google.com/docs/auth/users)

1. We will primarily use email and password auth for learning. Feel free to use other forms of auth in your exercises and projects.
2. The Firebase Auth instances provides convenient access to the currently logged-in user. We can use this throughout our app.
3. Auth listeners provide a convenient way to trigger relevant components to re-render when a user logs in or out.

### [Manage Users](https://firebase.google.com/docs/auth/web/manage-users)

1. We will almost certainly want to retrieve current user from the Auth object in our apps, e.g. to display logged-in user in places such as navbars, profile pages and comment bars.

### [Firebase Storage Basic security rules](https://firebase.google.com/docs/rules/basics?authuser=0\&hl=en#cloud-storage)

{% embed url="<https://firebase.google.com/docs/rules/basics?authuser=0&hl=en#cloud-storage>" %}

1. When you have successfully setup firebase authentication you can update your security rules for Firebase storage.


# 2.3.4: Firebase Hosting

## Learning Objectives

1. Firebase Hosting allows us to deploy web applications easily and efficiently with configuration to support React Router's `BrowserRouter`
2. How to deploy our apps to Firebase Hosting

### Introduction

{% embed url="<https://youtu.be/jsRVHeQd5kU>" %}
Firebase Hosting is a simple web-hosting tool that supports custom configuration. Source: Firebase
{% endembed %}

[Firebase Hosting](https://firebase.google.com/docs/hosting) is a simple and robust web-hosting tool that allows us to deploy our static apps (like React apps) with custom configuration to support features such as React Router's `BrowserRouter`. It otherwise performs generally the same functionality as GitHub Pages that we used previously.

Read more on what Firebase Hosting can do for us [here](https://firebase.google.com/docs/hosting/use-cases).

### [Get started](https://firebase.google.com/docs/hosting/quickstart)

1. We may want to read this in tandem with [Create React App's deploy instructions for Firebase](https://create-react-app.dev/docs/deployment#firebase).
   1. We can skip the warning about `service-worker.js` because we do not use that file in our repos at Rocket. Rocket deleted this file from Create React App starter code because service workers are for progressive web apps ("PWAs", web apps that run like native mobile apps on mobile devices) and we are not building PWAs.

### [Configure hosting behaviour](https://firebase.google.com/docs/hosting/full-config#rewrites): Set up `rewrites` to show the same content for multiple URLs

We will need this step to deploy our React apps with React Router `BrowserRouter` functionality.

1. [Create React App's deploy instructions for Firebase](https://create-react-app.dev/docs/deployment#firebase) should take care of this for us automatically if we reply "Yes" to the option to "Configure as a single-page app (rewrite all urls to /index.html)?".

### [Basic Security Rules](https://firebase.google.com/docs/rules/basics?authuser=0\&hl=en)

{% embed url="<https://firebase.google.com/docs/rules/basics?authuser=0&hl=en>" %}

If you are unable to access the Firebase Realtime Database or Firebase Storage following deployment online, please checkout the document above. You may need to update your security rules for each Firebase application that is associated to the application. You can find this in the Rules section of each app.

### Sample Deployment Legacy (CRA)

{% embed url="<https://youtu.be/AUopm8le7Vc>" %}
Firebase Hosting
{% endembed %}


# 2.3.5: Firebase Techniques

## Learning Objectives

1. Learn how to update a User's stored information on Firebase for greater user interaction
2. Learn how to setup email verification if your users forget their passwords

### Introduction

When developing React Firebase Applications with Authentication systems you unlock a plethora of utilities that allow developers to create intricate and complex applications. In this section, we will look at a few techniques that facilitate greater user interaction as well as  helping your users feel more supported during their experience. It should be noted that when applications are launched, features while vital are just as important as user experience.

## [Updating User information](https://firebase.google.com/docs/auth/web/manage-users#update_a_users_profile)

To update a users information that is tied to the Firebase user object is a few lines of code, but it can be difficult to align state with the updated information. To update the current user information we utilise the `updateProfile` method where we pass in the current user from the auth object and any information that we wish to update. Here is a sample implementation of the `updateProfile` method:

{% code title="updateProfile method" lineNumbers="true" %}

```jsx
 updateProfile(auth.currentUser, {
      displayName: displayName,
      photoURL: photoUrl,
    })
      .then(() => {
        auth.currentUser.reload().then(() => {
          const user = auth.currentUser;
          props.setUser(user);
          props.setShowUpdateUserForm(false);
        });
      })
      .catch((e) => {
        console.log(e);
      });
```

{% endcode %}

In order to update the users information you will first need to capture it using form inputs and the like, then you can send the captured information to Firebase for storage, in the example above, we capture a users `displayName` and `photoURL`. The `updateProfile` method will set the new information passed as the second argument, onto the Firebase server, but this will not reflect within your application. To align the updated profile online to your React state, we can view the latter half of the code above.

To refresh the current user within the browser window, we invoke the `auth.currentUser.reload()` method, we can then utilise a `.then` callback function that will run after the user had been updated. This will allow us to get the most current user object, as we can see on line 8. Following this, the setUser function is utilised to update the application to the current updated user on Firebase. To see how this code works checkout the [code here](https://github.com/rocketacademy/firebase-examples-3.2/tree/advanced-firebase). Make sure that you are on the `advanced-firebase` branch if you want to clone this repo onto your machine,  after cloning, cd into the directory and run the commands: `npm install` followed by `npm run dev`, then open a browser and navigate to "<http://localhost:5173>" to see the application.&#x20;

Note you will need to setup your own firebase credentials and apps online to run it correctly.&#x20;

## [User forgotten password](https://firebase.google.com/docs/auth/web/manage-users#send_a_password_reset_email)

There are often times where users forget passwords and in these moments its vital that Applications can support them in their time of need. To set this up with Firebase is relatively straightforward, the method required for this is called `sendPasswordResetEmail` and is passed the `auth` object that is setup in `firebase.jsx` and email of the user who is recovering their email. Make sure you capture the users email as it is required for this to work, moreover the users will need access to this email to click on the click and alter their password.&#x20;

```jsx
      <button onClick={() => sendPasswordResetEmail(auth, email)}>
        Forgotten Password?
      </button>
```

This is a basic implementation of of the code required to help a user to set a new password provided they have access to the email provided. To see how this code works checkout the [code here.](https://github.com/rocketacademy/firebase-examples-3.2/tree/advanced-firebase-II)&#x20;

Make sure that you are on the `advanced-firebase-II` branch if you want to clone this repo onto your machine,  after cloning, cd into the directory and run the commands: `npm install` followed by `npm run dev`, then open a browser and navigate to "<http://localhost:5173>" to see the application.&#x20;

Note you will need to setup your own firebase credentials and apps online to run it correctly.&#x20;


# 2.E: Exercises


# 2.E.1: Weather App

## Learning Objectives

1. Know how to send an HTTP request and handle response data in a frontend app
2. Know how to send an AJAX request and load response data in a React app
3. Know how to chain promises with multiple AJAX calls
4. Know how to read API documentation to use a new API

## Introduction

We will build a weather app that shows the latest weather forecast for a city that a user enters.

## Setup

1. Fork and clone the [Rocket Academy Weather App Repo](https://github.com/rocketacademy/weather-app-3.2)
2. [Create an Open Weather account](https://home.openweathermap.org/users/sign_up) to access Open Weather's free weather API. After confirming your email you will receive an API key to use to make API requests. <mark style="color:red;">**This can take up to 24 hours so please do this during pre-class.**</mark>&#x20;

## Base: Show current weather for user-provided city

### Instructions

1. Create an input field where users can input the city they would like to check the weather for. Provide instructions on the page so users know to enter a city name in the input.
2. When a user inputs a city name, use [Open Weather's current weather data API](https://openweathermap.org/current) to retrieve the weather in that city and display it to the user. The app should update the weather when the user inputs a new city or submits the same city again.
   1. To install [Axios](https://axios-http.com/docs/intro) to make requests, run `npm i axios` and import Axios from the relevant component.
   2. We will send GET requests because we are retrieving and not creating or updating any data.
   3. Notice the API URL uses [URL query parameters](https://en.wikipedia.org/wiki/Query_string#Structure) to customise the API call. We specify query parameters in key-value pairs separated by `=`, where we separate each key-value pair with `&`.
   4. When developing with APIs, feel free to `console.log` API responses to understand the format of the response before writing code logic. See below code example for an illustration.
   5. We will need to use [Open Weather's geocoding API](https://openweathermap.org/api/geocoding-api) to translate location names to coordinates before querying the current weather data API. You may find it helpful to chain promises with `.then` syntax.
      1. To chain multiple asynchronous function calls with `.then`, we can return the promises of the subsequent function calls in their `.then` callbacks instead of creating a nested `.then`. See example below for illustration.
   6. We may find it helpful to specify `metric` units for the `units` parameter of the API. This will return all temperature values in Celsius instead of Kelvin.
   7. Consider displaying the relevant icon next to the weather. Open Weather returns an icon code with weather info and we can retrieve the relevant icon using [Open Weather's Icon URLs](https://openweathermap.org/weather-conditions) and an HTML `img` tag.

{% hint style="info" %}
**Making our API key public**

By making API requests to Open Weather directly from our frontend app, we are effectively making our Open Weather API public because all frontend code is visible to users. This is discouraged in production apps because hackers can use our Open Weather account to make requests for free. We will learn how to build backend servers to hide sensitive data such as API keys in Module 3.
{% endhint %}

### Example: `console.log` response to understand response format

We can `console.log` the response to the API request to understand its format before we try to parse data from the response.

{% code title="App.jsx" %}

```jsx
handleSubmit = (event) => {
  event.preventDefault();
  axios
    .get(
      `https://api.openweathermap.org/geo/1.0/direct?q=${cityInputValue}&limit=1&appid=${OPEN_WEATHER_API_KEY}`
    )
    .then((response) => {
      console.log(response);
      // Write remaining logic once we understand response format
    });
};
```

{% endcode %}

The logging revealed that the data I want is in `response.data[0]`.

![console.log can help us reveal the format of an API response. Source: Rocket Academy](/files/ExKdqMdB7LvkNsLz2lv3)

### Example: Chain multiple Axios requests without nesting

Promise syntax is flexible, and there are preferred and less-preferred ways of handling promises. Rocket prefers we only have 1 level of nesting for chained promises for readability.

#### Bad

We should never need more than 1 level of nesting for `.then`s. This makes our code harder to read, because the `.then` execution flow becomes non-linear.

{% code title="App.jsx" %}

```jsx
handleSubmit = (event) => {
  event.preventDefault();
  axios
    .get(
      `https://api.openweathermap.org/geo/1.0/direct?q=${cityInputValue}&limit=1&appid=${OPEN_WEATHER_API_KEY}`
    )
    // City geo data is in response.data[0]
    // Arrow functions with no curly braces return value after arrow
    .then((response) => response.data[0])
    .then((cityGeoData) =>
      axios
        .get(
          `https://api.openweathermap.org/data/2.5/weather?lat=${cityGeoData.lat}&lon=${cityGeoData.lon}&appid=${OPEN_WEATHER_API_KEY}&units=metric`
        )
        .then((response) => {
          const { data: weatherData } = response;
          console.log(weatherData);
        })
    );
};
```

{% endcode %}

#### Good

We can return the promise returned by the 2nd `axios.get` in its `.then` callback, and obtain the result of that promise in the subsequent `.then`. This allows us to have only 1 level of nesting.&#x20;

`.then` callbacks accept both values and promises as return values. If a previous `.then` callback returns a promise, the subsequent `.then` callback will receive that promise's resolved value as a parameter. Read more on `.then` behaviour in [official docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then).

{% code title="App.jsx" %}

```jsx
handleSubmit = (event) => {
  event.preventDefault();
  axios
    .get(
      `https://api.openweathermap.org/geo/1.0/direct?q=${cityInputValue}&limit=1&appid=${OPEN_WEATHER_API_KEY}`
    )
    // City geo data is in response.data[0]
    // Arrow functions with no curly braces return value after arrow
    .then((response) => response.data[0])
    .then((cityGeoData) =>
      axios.get(
        `https://api.openweathermap.org/data/2.5/weather?lat=${cityGeoData.lat}&lon=${cityGeoData.lon}&appid=${OPEN_WEATHER_API_KEY}&units=metric`
      )
    )
    .then((response) => {
      const { data: weatherData } = response;
      console.log(weatherData);
    });
};
```

{% endcode %}

## Comfortable: Show hourly and daily forecasts for coming days

In addition to the current weather, display a daily forecast, represented by hourly data to the user in tables. You may find the [Open Weather API documentation](https://openweathermap.org/forecast5) helpful.

## More Comfortable: Show forecast data in a graph

Render the forecast data in a graph instead of a table. You may find React chart libraries like [Recharts](https://recharts.org/en-US/) helpful.

## Submission

Submit a pull request to the `main` branch of Rocket's Weather App repo and share your PR link in your section Slack channel.

If you would like to deploy your app to the internet, follow Vitejs GitHub Pages [deployment instructions here](https://vitejs.dev/guide/static-deploy.html).

{% hint style="info" %}
**Use HTTPS URLs for API requests for deployment**

HTTPS sites can only make HTTPS requests and not HTTP requests. To deploy our app to GitHub Pages, update all API URLs in our app to use HTTPS instead of HTTP (i.e. `https://myurl.com` instead of `http://myurl.com`. Open Weather Geocoding and Weather Icons docs share HTTP links, but luckily they both also support HTTPS.
{% endhint %}

## Reference Solution

Here is [reference code](https://github.com/rocketacademy/weather-app-3.2/tree/solution-base) and a [reference deployment](https://rocketacademy.github.io/weather-app-3.2/) for this exercise. You can do better!


# 2.E.2: Instagram Chat

## Learning Objectives

1. Install, import and use a 3rd-party library in React
2. Understand how to use Firebase Realtime Database
3. Understand how to structure chat data in a NoSQL JSON database
4. Know how to read documentation to apply a new technology

## Introduction

This is the first of multiple exercises culminating in an Instagram clone. We start with chat because it a common example and will allow us to warm up to network requests, promises and Firebase.

## Setup

1. Fork and clone the [Rocket Academy Instagram starter repo](https://github.com/rocketacademy/instagram-3.2)
   1. Run `npm install` to install packages in `package.json` after cloning
2. [Add Firebase to our project](https://firebase.google.com/docs/web/setup)
   1. Rocket recommends following the text and not video instructions on the Firebase docs page because the video demonstrates creating a Firebase app from scratch, not with Rocket's starter repo that includes starter code from Vitejs.
   2. Create a Firebase project in the Firebase console and call it "Rocketgram" (calling it "Instagram" may give our users scam warnings after we deploy)
      1. There is no need to enable Google Analytics for this project. Disable that option when creating a project to avoid creating a Google Analytics account.
   3. Register our app with our Firebase project - <mark style="color:red;">**you can do this in your Firebase console underneath your registered firebase project,**</mark>&#x20;
      1. We can call our app "Rocketgram"
      2. No need to set up Firebase Hosting for now
      3. No need to `npm install firebase` because Rocket has already installed it in `package.json`
      4. Replace the contents of the `firebaseConfig` object in `src/firebase.jsx` with our app's config details. Consider adding this to a .env. We will retrieve the `databaseUrl` property after the next step.
3. Set up Firebase Realtime Database in the repo as per the [official Firebase documentation](https://firebase.google.com/docs/database/web/start)
   1. Start from Create a Database; we just completed the prerequisite in the previous step
      1. When creating a database in the Firebase console, select the location nearest to you when prompted to choose "Realtime Database location"
      2. Select "Start in test mode" for security rules; we can set up more stringent security rules later after learning about authentication.
         1. When we start in test mode, in 30 days Firebase may notify us they will turn off database access unless we update security rules. When that happens, feel free to set both read and write access to `true`, even though it is insecure for now. Nobody will hack us because our apps are not "important", and if your app is storing important data please let your section leader know so we can secure it better.
   2. Skip "Configure Realtime Database Rules" section in the docs; we will set up database rules after learning authentication.
   3. Initialise the Realtime Database JavaScript SDK
      1. Rocket has set up initialisation code in the starter repo in `src/firebase.jsx`
      2. Find your Realtime Database URL as per instructions in this section and paste it as the value of the `databaseURL` property in the `firebaseConfig` object in `src/firebase.jsx`. Your database URL should look something like `https://rocketgram-abc123-default-rtdb.asia-southeast1.firebasedatabase.app/`.
      3. Once we have added the database URL to `firebase.jsx`, we should be able to start using our database in React components that import the database from `firebase.jsx`. See how we import the database in `App.jsx` for an example.
4. Practice safe sharing, create implement your .env so that you do not share your Firebase credentials online when pushing to GitHub.

## Familiarise yourself with starter code

1. As in previous exercises, most of this exercise's code and logic is in `App.jsx`.
   1. Notice the use of the `useState` to initialise the `messages` state.
   2. Notice the use of `useEffect` to emulate the lifecycle componentDidMount to add a Firebase's listener when the Component mounts.
   3. Notice the use of `writeData` helper method to save a message when the user clicks Send.
   4. Notice the mechanics of sending and retrieving data from Firebase with `ref`, `push`, `set`, `onChildAdded`.
2. Notice the boilerplate Firebase config in `firebase.jsx`. We will need to fill this in with our Firebase app's details.
   1. Notice how `firebase.jsx` exports the Realtime Database instance that we import in `App.jsx` to access the online database.

## Base: Create form and implement chat functionality

Add UI and logic to `App.jsx` to accept user input in a form, save it in Firebase on submit and render on the page after submit.&#x20;

1. We may find material on controlled forms useful from Module 1
2. We should be able to open multiple client apps, e.g. multiple browser tabs or windows connected to our app and have them chat with each other in real time. We will be able to incorporate usernames once we implement authentication later in this module.

## Comfortable: Save and render date and time of each message

Save and render the date and time of each message in Firebase and our app respectively. We can use JavaScript's `Date` object to generate and send the current datetime to Firebase when a user sends a message. After retrieving datetimes with messages we can use `Date`'s built-in formatting methods to render datetime nicely next to each message.

## More Comfortable: Style the app

Customise the UI to make it visually appealing. Rocket did not customise the UI in our starter code or solution because our focus has been on Firebase mechanics.

## Submission

Submit a pull request to the `main` branch of Rocket's Instagram repo and share your PR link in your section Slack channel.

If you would like to deploy your app to the internet, follow Vitejs GitHub Pages [deployment instructions here](https://vitejs.dev/guide/static-deploy.html).

## Reference Solution

Here is [reference code ](https://github.com/rocketacademy/instagram-3.2/tree/solution-chat-base)for this exercise. You can do better!

To play with the solution, clone it, make sure you are on the `solution-base` branch, run `npm i` and `npm run dev`. Then open a browser and navigate to <http://localhost:5173>. We did not host a reference deployment for this solution because we will build on this repo in the following exercises and will host a reference deployment for the final one.


# 2.E.3: Instagram Posts

## Learning Objectives

1. Understand how to use JavaScript promises
2. Understand how to use Firebase Storage
3. Understand how cloud storage works: upload files, store references to those files in our database
4. Know how to read documentation to apply a new technology

## Introduction

We will build on the previous exercise to incorporate file uploads and store data as posts to display on our shared feed.

## Setup

1. Start with the code we wrote in the previous exercise in our forked and cloned copy of the [Rocket Academy Instagram starter repo](https://github.com/rocketacademy/instagram-3.2).
2. Set up Firebase Storage in the repo as per the [official Firebase documentation](https://firebase.google.com/docs/storage/web/start)
   1. Start from "Create a default Cloud Storage bucket"; we just completed the prerequisite in the previous step
      1. Choose "Start in Test mode" when setting up Cloud Storage to avoid setting up security rules for now. We will address this after learning Firebase Authentication.
      2. Choose a Cloud Storage location nearest to your users. See [Firebase docs](https://firebase.google.com/docs/projects/locations) for a list of locations and their descriptions. Singapore is `asia-southeast1`.&#x20;
   2. In "Add your bucket URL to your app", our bucket URL may already be in our Firebase config in `firebase.jsx`, but we will want to import `getStorage` from `firebase/storage` and `export const storage = getStorage(firebaseApp);` from `firebase.jsx` with the same pattern we used for Realtime Database. We can then import `storage` from `./firebase` in `App.jsx` like what we did with Realtime Database.
   3. We can ignore the options in "Advanced setup" for now; nothing there that we should need yet
3. Practice safe sharing, create implement your .env so that you do not share your Firebase credentials online when pushing to GitHub.

## Base: Upgrade form to include file uploads, build news feed

1. Upgrade the form we created in Instagram Chat to accept file uploads in addition to text. Form submissions will now be considered "posts" that we will save to our database and render in our news feed.&#x20;
   1. We can use `<input type="file" />` to accept file inputs in our form. See code snippet below for an example of how to use file input fields with React.
   2. [Here](https://github.com/rocketacademy/bootcamp3.0-docs/tree/main/2-full-stack/2.e-exercises/photos) are nice sunset images you can use as sample images
   3. On form submit:
      1. Upload the file to Firebase Storage
      2. Save the response, the file's database URL together with the post text in Realtime Database.&#x20;
         1. **Note**: Be careful when using promises we may have to wait for the upload and `getDatabaseURL` promises to resolve before we can save the database URL.
         2. **Note:** We may want to import and use functions from `firebase/storage` as per the Firebase Upload Files tutorial.
         3. **Note:** We may want to use [import aliases](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) when importing functions of the same name such as `ref` from multiple modules, e.g. both `firebase/storage` and `firebase/database`. See code snippet below for example.
2. Upgrade the UI of our app to render posts nicely. Consider using [React Bootstrap Cards](https://react-bootstrap.github.io/components/cards/) as a simple solution.
   1. You may find that the images we upload render too large. Rocket found that creating and applying a CSS class on card images and setting `width` to `50vw` and `height` to `30vh` gave a good look.

{% hint style="info" %}
**Import Bootstrap CSS to use React Bootstrap**

If we wish to use React Bootstrap, don't forget to [import Bootstrap CSS](https://react-bootstrap.github.io/getting-started/introduction/#css) in either main`.jsx` or `App.jsx`.

If you see the following Webpack warning, this is an [open Bootstrap issue](https://github.com/twbs/bootstrap/issues/36259), non-breaking and should be resolved by Bootstrap soon. Can ignore for now.

```
Warning
(6:29521) autoprefixer: Replace color-adjust to print-color-adjust. The color-adjust shorthand is currently deprecated.
```

{% endhint %}

### Example: File input field in React

{% code title="File input example" lineNumbers="true" %}

```jsx
import { useState } from "react";

function App() {
  const [textInputValue, setTextInputValue] = useState("");
  const [fileInputFile, setFileInputFile] = useState(null);
  const [fileInputValue, setFileInputValue] = useState("");
  return (
    <>
      <h1>Instagram Bootcamp</h1>
      <div className="card">
        <form {/* Add in submit handler*/}>
          <input
            type="file"
            value={fileInputValue}
            onChange={(e) => {
              setFileInputFile(e.target.files[0]);
              setFileInputValue(e.target.value);
            }}
          />
          <br />
          <input
            type="text"
            value={textInputValue}
            onChange={(e) => setTextInputValue(e.target.value)}
          />
          <input
            type="submit"
            value="Send"
            // Disable Send button when text input is empty
            disabled={!textInputValue}
          />
        </form>
      </div>
    </>
  );
}
```

{% endcode %}

### Example: Import aliases for multiple named imports of the same name from different modules

The following code is in the reference solution. We give [aliases](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) using `as` syntax to the named imports `ref` from both `firebase/database` and `firebase/storage`.

```jsx
import { onChildAdded, push, ref as databaseRef, set } from "firebase/database";
import {
  getDownloadURL,
  ref as storageRef,
  uploadBytes,
} from "firebase/storage";
```

## Comfortable: Implement likes

1. Implement like functionality on posts. Every post in the news feed has a heart-shaped like button that increments the posts' like count by 1 when we toggle it on. When we toggle the like button off, our app decrements the relevant posts' like count.&#x20;
   1. This feature will be buggy for now (e.g. we can refresh our page and like the same post again for duplicate likes) until we implement authentication in the next exercise.

## More Comfortable: Comments

Implement commenting functionality on posts. Every post in the news feed has a comment bar that allows users to leave comments. We can store comments together with their post in our database.

## Submission

Submit a pull request to the `main` branch of Rocket's Instagram repo and share your PR link in your section Slack channel.

If you would like to deploy your app to the internet, follow Vitejs GitHub Pages [deployment instructions here](https://vitejs.dev/guide/static-deploy.html).

## Reference Solution

Here is [reference code](https://github.com/rocketacademy/instagram-3.2/tree/solution-posts-base) for this exercise. You can do better!

To play with the solution, clone it, make sure you are on the `solution-base` branch, run `npm i` and `npm run dev`. Then open a browser and navigate to <http://localhost:5173>. We did not host a reference deployment for this solution because we will build on this repo in the following exercises and will host a reference deployment for the final one.


# 2.E.4: Instagram Auth

## Learning Objectives

1. Know how to decompose complex components into multiple smaller, more manageable components
2. Understand where to put authentication in a UX flow to lure users in and give them as much reason to login as possible
3. Understand how to use Firebase Authentication
4. Know how to read documentation to apply a new technology

## Introduction

We will build on the previous exercise to incorporate authentication and user information on all posts, likes and comments.

## Setup

1. Start with the code we wrote in the previous exercise in our forked and cloned copy of the [Rocket Academy Instagram starter repo](https://github.com/rocketacademy/instagram-3.2)
2. Set up Firebase Authentication in our local `firebase.jsx` as per the [official Firebase documentation](https://firebase.google.com/docs/auth/web/start)
   1. Under "Add and initialize the Authentication SDK", we will need to import `getAuth` and export a named export with the Auth object, like `export const auth = getAuth(firebaseApp);`
   2. Skip "(Optional) Prototype and test with Firebase Local Emulator Suite" and everything below it for now; that content will be covered in the next step.
3. [Enable Email/Password sign-in](https://firebase.google.com/docs/auth/web/password-auth#before_you_begin) in the Firebase console (Step 3 in the linked docs)
   1. Once in the Auth section of our app in the Firebase console, click "Get started" button
   2. Choose the Email/Password sign-in method from the menu
   3. Enable Email/Password
4. Practice safe sharing, create implement your .env so that you do not share your Firebase credentials online when pushing to GitHub.

## Base: Users must login to post, posts have author identity

1. Refactor app into multiple components each in separate files for maintainability.
   1. Now that our app is starting to become complex (100+ lines of news feed code alone in `App.jsx`), we may want to consider refactoring `App` into multiple components for maintainability before adding new functionality such as auth.
   2. In our reference solution we separate `App.jsx`, `Composer.jsx` (the form to create new posts) and `NewsFeed.jsx` files for their respective components and put them in a c`omponents` folder in `src` that contains the component `.jsx` files and their relevant `.css` files.
      1. This will require some re-wiring of relative imports to files such as `src/firebase.jsx` and in files such as `src/main.jsx`.
   3. Separate composer state and logic into a `Composer` component in `Composer.jsx` and news feed state and logic into a `NewsFeed` component in `NewsFeed.jsx`. Import both `Composer` and `NewsFeed` in `App.jsx` to render them in the `App` component as before. Revise [React docs for composing components](https://reactjs.org/docs/components-and-props.html#composing-components) for a refresher.
   4. If you customised your UI in previous exercises, feel free to decompose your components however makes sense for your UI.
2. Update our user flow such that a user needs to log in to post. They should still see the news feed (without composer) before logging in (to lure them in). But when they are not logged in, we display a button to "Create Account or Sign In" instead of the composer.
   1. Consider storing `loggedInUser` as state in `App` component and using the `onAuthStateChanged` listener in `App`'s `componentDidMount` to keep `loggedInUser` updated. `App` can use `loggedInUser` to determine whether to render the "Create Account or Sign In" button or the composer.
   2. Consider also storing `shouldRenderAuthForm` boolean state in `App` component and creating a class method `toggleAuthForm` in `App` that toggles `shouldRenderAuthForm`. When an unauthenticated user clicks "Create Account or Sign In" button, `App` can call `toggleAuthForm` and render the auth form instead of the news feed. Once the user authenticates, auth form logic can call `toggleAuthForm` again for `App` to render composer and news feed instead of auth form.
   3. Create a new `AuthForm` component in `components/AuthForm.jsx` for the auth form and import it where relevant in `App`.
      1. You may find the [email HTML input type](https://www.w3schools.com/tags/att_input_type_email.asp) and [password HTML input type](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/password) helpful for email validation and hiding passwords in the password field
3. All posts should now render the author's identity as part of the post.

{% hint style="info" %}
**Import Bootstrap CSS to use React Bootstrap**

If we wish to use React Bootstrap, don't forget to [import Bootstrap CSS](https://react-bootstrap.github.io/getting-started/introduction/#css) in either `main.jsx` or `App.jsx`.

If you see the following Webpack warning, this is an [open Bootstrap issue](https://github.com/twbs/bootstrap/issues/36259), non-breaking and should be resolved by Bootstrap soon. Can ignore for now.

```
Warning
(6:29521) autoprefixer: Replace color-adjust to print-color-adjust. The color-adjust shorthand is currently deprecated.
```

{% endhint %}

{% hint style="info" %}
**Test using incognito mode**

Use [incognito mode](https://support.google.com/chrome/answer/95464?hl=en\&co=GENIE.Platform%3DDesktop) to open our app without storing logins across sessions. Without implementing logout functionality, our browsers may cache logins making it more difficult to test login functionality more than once when not in incognito mode.
{% endhint %}

## Comfortable: Identity in navbar

1. Display the logged-in user's identity in a navbar at the top of the app. Consider using [React Bootstrap's `Navbar` component](https://react-bootstrap.github.io/components/navbar/#text-and-non-nav-links) for this.

## More Comfortable: Identity for likes and comments

1. If you haven't already, implement like and/or comment functionality for posts from Comfortable and More Comfortable in the Instagram Posts exercise
2. Likes should now be associated with a user's identity, and a user can only like a post at most once
3. Comments should show the author's identity like posts

## Submission

Submit a pull request to the `main` branch of Rocket's Instagram repo and share your PR link in your section Slack channel.

If you would like to deploy your app to the internet, follow Vitejs GitHub Pages [deployment instructions here](https://vitejs.dev/guide/static-deploy.html).

## Reference Solution

Here is [reference code ](https://github.com/rocketacademy/instagram-3.2/tree/solution-auth-base)for this exercise. You can do better!

To play with the solution, clone it, run `npm i` and `npm start`. We did not host a reference deployment for this solution because we will build on this repo in the following exercises and will host a reference deployment for the final one.

### Sample Implementation Firebase Auth Legacy (Slightly different code)

{% embed url="<https://youtu.be/2tsYhkhfHIc>" %}
Firebase Auth
{% endembed %}

{% embed url="<https://youtu.be/OI676T5g6TM>" %}
Firebase Auth Functionalities
{% endembed %}

{% embed url="<https://youtu.be/qhuzwubCEcs>" %}
Firebase Auth&#x20;
{% endembed %}

Please checkout the finished code in this [repository](https://github.com/rocketacademy/firebase-examples-3.2/tree/auth), ensure that you're on the `auth` branch. If you want to test out the application on your machine you will need to have registered an Application on Firebase with Realtime Database, Storage and Authentication activated. Use the `sample.env` within the application to create an `.env` file with your Firebase credentials. With this in mind if you want to run the application on your machine you will need to install the dependencies with the command `npm install` after the installation you can then run the application with the command `npm run dev`.  Then open a browser of your choice and navigate to  <http://localhost:5173>.


# 2.E.5: Instagram Routes

## Learning Objectives

1. Understand how to use React Router to build React apps with multiple URL paths
2. Understand how to split component logic to effectively have multiple pages served by the same React app
3. Understand how to refactor class components to be functional components with React Hooks
4. Understand how to deploy an app with Firebase Hosting
5. Know how to read documentation to apply a new technology

## Introduction

We will build on previous Instagram exercises to incorporate React Router and create standalone pages for each post with relevant URLs.

## Setup

1. Start with the code we wrote in the previous exercise in our forked and cloned copy of the [Rocket Academy Instagram starter repo](https://github.com/rocketacademy/instagram-3.2)
2. Set up React Router in our repo as per the official [React Router documentation](https://reactrouter.com/en/6.18.0/start/overview#nested-routes)
3. Practice safe sharing, create implement your .env so that you do not share your Firebase credentials online when pushing to GitHub.

{% hint style="info" %}
**We will deploy on Firebase Hosting instead of GitHub Pages**
{% endhint %}

## Base: Split `Home` and `AuthForm` pages into separate routes

In Instagram Auth we created an `AuthForm` component that renders instead of the `NewsFeed` component when our user wants to sign in. We will now create separate routes for `AuthForm` (`/authform`) and `NewsFeed` (`/`) components to make it easier for users to navigate to the auth form and news feed respectively. Consider referring back to the [React Router Implementation section](https://reactrouter.com/en/6.18.0/start/overview#client-side-routing)..

Now that we will use Links and Routes to navigate between our auth form and news feed, we no longer need `shouldRenderAuthForm` state and the `toggleAuthForm` method to determine whether to render the auth form. We can remove all mentions of `shouldRenderAuthForm` and `toggleAuthForm` from `App`, and update `toggleAuthForm` usage to either a React Router `Link` to `/authform` or `useNavigate`/`navigate` to `/` after auth form submission.

You may remember that we cannot use React Hooks in class components. There is no need to rewrite all of our components to be functional components, but we will need to rewrite ones such as `AuthForm` that need the React Router `useNavigate` hook.&#x20;

## Comfortable: Dedicated page and route for each post

Clicking on posts in the news feed navigates to a standalone page for the clicked post. The standalone page should have a URL that uniquely identifies that post, and a back button to get back to the news feed. Create a new component in a new file for pages for individual posts. We may find [Reading URL Params](https://reactrouter.com/docs/en/v6/getting-started/tutorial#reading-url-params) in React Router helpful for creating and using a relevant URL for each post.

## More Comfortable: Navbar, chat page

Re-create our chat page from Instagram Chat as a separate component. Add a navigation bar to the app and allow users to toggle between news feed and chat pages via navigation links. Toggling between features updates the app URL for the relevant feature.

## Submission

Submit a pull request to the `main` branch of Rocket's Instagram repo and share your PR link in your section Slack channel.

If you would like to deploy your app to the internet, follow Vitejs GitHub Pages [deployment instructions here](https://vitejs.dev/guide/static-deploy.html). Note that you will need to add the repo name within React Router's to and path properties.&#x20;

## Reference Solution

Here is [reference code](https://github.com/rocketacademy/instagram-3.2/tree/solution-routes-base) and a [reference deployment](https://instagram-bootcamp-3.web.app/) for this exercise. You can do bette&#x72;**!**

You may see the following warning from Chrome when visiting the reference deployment. This may be because Rocket used "Instagram" as our app name and we have "instagram" in our URL. To visit the site anyway, click "Details" and "visit this unsafe site" like in the screenshots below.

![Chrome warns us of deceptive sites. Source: Rocket Academy](/files/l3ixR9HgUwLkZPixvjEQ)

![To visit the site anyway, click "visit this unsafe site". Source: Rocket Academy](/files/J0aDAYEmE0eyKjjVmUGC)


# 2.P: Full-Stack App (Firebase)

## Introduction

Build an Application in a group of 2 or 3 that solves a problem you have using React and Firebase. Feel free to use any 3rd-party libraries and Firebase features beyond the ones we have learnt. In this project we are utilising Firebase a rudimentary backend and as a database.

## Requirements

### App Stack

This project must be a Frontend React Application that utilises React as well as Firebase products, including Realtime Database, Storage, and Authentication.

### User Interface

* [ ] The user interface of the Application is consistently styled across all components and screens
* [ ] The Application is accessible on various devices and screen sizes
* [ ] The Application is intuitive, usable and easy to navigate
* [ ] Application has been styled with superb custom CSS, [React Bootstrap](https://react-bootstrap.github.io/components/alerts), [MUI](https://mui.com/core/) or another component UI or CSS framework

### Functionality&#x20;

* [ ] The core functionalities of the application work as intended and expected
* [ ] The Application handles props effectively across components
* [ ] The Application manages and updates state effectively
* [ ] Interactivity:
  * [ ] The Application contains at least 1 input that captures user input to alter Application state&#x20;
  * [ ] The Application contains at least 1 call to action that alters Applications state
  * [ ] The Application can reflected updated state in the UI
* [ ] Complexity:
  * [ ] Application has at least 2 levels of components eg: \
    App component and 1 or more child components
  * [ ] Application demonstrates the capability to lift up state
* [ ] Application is required to persist data utilising Firebase Realtime Database (or an alternative like Firebase Firestore)
* [ ] Application must able to store files utilising Firebase Storage
* [ ] Application must contain an authentication system that leverages Firebase Authentication
* [ ] Application must contain multiple pages this can be implemented with React Router
* [ ] Application must contain at least 1 request to an external API using Axios or Fetch

### Code Quality

* [ ] Application is organised as well as structured, it follows practices of component separation and has a good folder structure
* [ ] The code is easy to comprehend and read
* [ ] The Application contains meaningful variable and function names
* [ ] Application contains components that can be reused
* [ ] The Application preforms well without unwarranted rendering
* [ ] The Application's code follows consistent coding conventions, regarding indentations and formatting
* [ ] The Application follows the correct naming, casing and commenting [best practices](/general-reference/naming-casing-and-commenting-conventions)

### Project Management&#x20;

* [ ] Application has been deployed with [Firebase Hosting](https://firebase.google.com/docs/hosting)
* [ ] Git repository contains commits for each feature with descriptive commit messages
* [ ] Application contains a README with the applications description, user stories and low-fidelity wireframes
* [ ] The README contains instructions on how to run the application&#x20;
* [ ] The group worked as a cohesive team to compelte the project&#x20;
* [ ] Every group member must contribute at least 1 feature into the Application

## Ideas

As before, try to find an idea that solves a problem you have. Now that we can persist data with Firebase and send HTTP requests to arbitrary APIs, there is virtually no limit to the type of app we can build. Be realistic about the scope of your project: 1 polished feature that solves a common or important problem is more valuable than many scrappy features of lower value.

While brainstorming ideas, visualise how you might present the project to a prospective employer. Is this project impressive because it solves an unaddressed problem? Because it is technically well-done? Because of the thoughtfulness of its UX?

Some APIs and libraries we can consider:

1. [Data.gov.sg real-time APIs](https://data.gov.sg/developer)
2. [Google Vision API](https://cloud.google.com/vision)
3. [Google Maps API](https://www.npmjs.com/package/google-map-react)

## Timeline

You will have roughly 8 course days to complete this project. We will observe the following timeline to keep us on track.

| Project Day | Checkpoint                                                                                                                                                                                                                 | Feedback                                                                                                                  |
| :---------: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
|      0      | <p><strong>Ideation phase 1</strong></p><p>Post project ideas in Slack for feedback</p>                                                                                                                                    | SL to review ideas and share feedback                                                                                     |
|      1      | <p><strong>Ideation phase 2</strong><br>Create planning docs: user stories, wireframes, kanban board</p>                                                                                                                   | SL to review planning docs and share feedback                                                                             |
|      2      | **Start implementation**                                                                                                                                                                                                   | -                                                                                                                         |
|      3      | -                                                                                                                                                                                                                          | -                                                                                                                         |
|      4      | -                                                                                                                                                                                                                          | -                                                                                                                         |
|      5      | <p><strong>MVP deadline</strong><br>Users can complete the primary user story</p>                                                                                                                                          | SL to review code in GitHub, share feedback                                                                               |
|      6      | -                                                                                                                                                                                                                          | -                                                                                                                         |
|      7      | <p><strong>Feature freeze</strong></p><p>No new features, focus on polishing existing features and code to be presentable</p>                                                                                              | SL to review progress and share post-feature-freeze suggestions                                                           |
|      8      | -                                                                                                                                                                                                                          | -                                                                                                                         |
|      9      | <p><strong>Project presentations</strong></p><p>Practise <a href="/pages/vnQ0MkMbmPv2pn2pzRko#presentations">explaining your work</a> to others. Other batches will join and we will celebrate each others' hard work.</p> | SL to review code in GitHub, share feedback in 30-minute [post-mortem meeting](/logistics/course-methodology#post-mortem) |
|      10     | <p><strong>Demo video</strong><br>Record a <a href="/pages/vnQ0MkMbmPv2pn2pzRko#demo-video">demo video</a> for employers and the public, embed in README</p>                                                               |                                                                                                                           |

## Project Management Suggestions

In addition to user story, wireframe and kanban board, now that we have a database (DB), Rocket recommends we plan the DB schema before starting. Our DB schema will change during app development, but planning ahead can reduce the number of changes. Rocket recommends we revise the [Firebase Realtime Database guide on structuring data](https://firebase.google.com/docs/database/web/structure-data) before starting, and reviewing the [Firebase Firestore guide on structuring data](https://firebase.google.com/docs/firestore/manage-data/structure-data) if we plan to use Firestore.

## How to code in a group

### General strategy

1. Have 1 person create a GitHub repo and invite other team members as collaborators
2. For each task in the kanban board, create a new feature branch from `main`. Name the branch after the task. When the task is done, push the feature branch to GitHub, create a pull request (PR) and merge the code into `main` from the PR in GitHub.

### How to pull and merge latest changes in `main` to feature branch

Team members will merge code to `main` regularly and we will want to incorporate those changes in our feature branch to ensure compatibility with `main`. Rocket recommends this operation before merging to `main` to test merge results on feature branch instead of `main`.

1. Save & commit all changes on the current (non-`main`) feature branch. Pull latest changes to `main` with `git pull origin main`.
2. Merge `main` to feature branch with `git merge main` while on feature branch
3. Resolve any conflicts on feature branch. Follow instructions in console, using `git status` to see what steps are needed.

### How to merge latest changes from feature branch to `main`

After committing changes and verifying our feature branch is compatible with `main`, we will merge our changes to `main` for our teammates to use.

1. Push feature branch to GitHub with `git push`, then create a PR to merge feature branch with `main` on GitHub.
2. After merging PR in GitHub, run `git pull origin main` to get latest `main` branch changes from GitHub.
3. Delete feature branch locally with `git branch -d <FEATURE-BRANCH-NAME>`
4. Delete feature branch on GitHub with `git push origin --delete <FEATURE-BRANCH-NAME>`

### How to avoid merge conflicts

Merge conflicts happen when Git is unsure how to merge 2 versions of a file. To resolve a merge conflict, use `git status` to find which files have conflicts, resolve the conflicts in each file by editing it to be what it should be, and run `git commit` to complete the merge. We can reduce the chance of merge conflicts by communicating often with our team and merging latest changes from `main` to our feature branch regularly.

## Setup

Start by forking [Rocket's Bootcamp Project 2 repo](https://github.com/rocketacademy/project2-3.2) that contains an empty CRA app. This will make it easier for SLs to review your code via pull requests.

## Deployment

Rocket recommends deploying to [Firebase Hosting](https://vitejs.dev/guide/static-deploy.html#google-firebase) as per ViteJs official docs because Firebase Hosting allows for client-side routing.

## Submission

1. Submit a pull request to Rocket's Project 2 repo
2. Add your Project 2 repo link to the Rocket Bootcamp Projects spreadsheet in your batch-specific sheet shared by your SL.&#x20;

## General Tips

1. Code the foundation of the app together before splitting up to code individual features. This will reduce merge conflicts and help everyone gain a common understanding of how the app should work.
2. Implement the primary user story first. What are users coming to your app to do? Ensure they are able to accomplish that before adding authentication and nice-to-have features.


# 3: Backend

## Learning Objectives

1. Backend refers to non-client computers that perform logic, store and serve data
2. Servers are computers without a screen that receive requests from clients and respond with data
3. SQL is the language for querying relational databases; PostgreSQL is a popular dialect
4. Sequelize is an ORM (Object-Relational Mapping) that enables us to write code that generates SQL
5. JWT authentication is the de-facto authentication standard
6. Sockets allow us to transmit data and update UIs in real-time
7. Deploy a backend server to Heroku that can store and serve data for our frontends

## Introduction

![We will now build the backend portion of our app architecture. Source: Rocket Academy](/files/YJdh1QzHGRfPm4jn0e5i)

In Module 3: Backend we will build a backend server that performs logic, stores and serves data to our frontends using the JavaScript server framework Express.js. Our backends will use relational (tabled-based) databases (aka SQL databases, pronounced "sequel") instead of the JSON-like databases we used with Firebase. Most companies use SQL databases for the majority of their use cases because SQL can be more structured has less potential for human error.


# 3.1: Express.js

Learning Objectives

1. Revise the HTTP Request and Response Cycle.
2. Express.js is a server application framework that helps us receive requests from clients and respond with data
3. Understand how to create routes and corresponding middleware functions that handle requests to those routes
4. Know how to parse URL path and query parameters in route middleware
5. Middleware functions are functions that run during the "request-response cycle" and have access to Express request and response objects

## HTTP Revision

{% embed url="<https://youtu.be/XoQPZyO4rMo>" %}
Http Request and Response Cycle
{% endembed %}

{% embed url="<https://youtu.be/M-cMnNBOgGc>" %}
HTTP Request Verb and Status Codes
{% endembed %}

## Introduction

{% embed url="<https://youtu.be/KAKkV0AimeM>" %}
Introduction to Express
{% endembed %}

Express.js is a server application framework that helps us receive requests from clients and respond with data. Servers are computers without a screen that perform logic on behalf of clients such as storing and retrieving data.

## Basic Express App

The following code is a minimal Express app that hosts a server at port 3000 and responds with "Hello, World!" at the root route, i.e. `localhost:3000` when run locally or `mysite.com` when deployed to `mysite.com`. [Check it out on StackBlitz](https://stackblitz.com/edit/basic-express-app-rocket?file=index.js), a popular online IDE!

{% code title="index.js" %}

```javascript
// require Express NPM library
const express = require('express');

// Declare the port to listen to and initialise Express
const PORT = 3000;
const app = express();

// Define a route and corresponding middleware function
app.get("/", (req, res) => {
  res.send("Hello, World!");
});

// Start the server
app.listen(PORT, () => {
  console.log(`Example app listening on port ${PORT}!`);
});
```

{% endcode %}

Let's break down the above code.

1. Requiring `express` imports the Express library for us to initialise, configure and run our server
2. `PORT` defines the port that our Express server will listen on. Recall from Module 2 that ports determine which applications receive which requests on servers. We use SCREAM\_CASE to define constant variables like `PORT` at the top of our files or in a separate constants file for easy access.
3. `const app = express()` initialises our Express application
4. `app.get` is a route middleware (more on this below) that routes requests to a specific URL path to a specific middleware function to handle that request
5. `req` and `res` parameters to the middleware function are Express [Request](https://expressjs.com/en/4x/api.html#req) and [Response](https://expressjs.com/en/4x/api.html#res) objects respectively
6. `res.send` is a [method of the Express Response object](https://expressjs.com/en/4x/api.html#res.send) that sends a response to the requesting client
7. `app.listen` tells the Express app to start listening for requests at the specified port and execute the specified callback function after successfully starting

In the following sections we will dig deeper into route middleware and middleware functions in general.

{% embed url="<https://youtu.be/0EhCLKlw5ng>" %}
Thunder Client && Expressjs
{% endembed %}

## Fruit Express App (Simple)

{% embed url="<https://youtu.be/AbAi44vQtuc>" %}
Express Fruit Application
{% endembed %}

Please checkout the finished code in this [repository](https://github.com/rocketacademy/m3_express_repo), ensure that you're on the `simple_express` branch if you want to test out the application on your machine you will need to install the dependencies with the command `npm install` after the installation you can then run the application with the command `node index.js`

## Routes

Routes (aka "route middleware", "routing methods") are middleware functions that define how servers handle requests to specific URL paths with specific URL methods. Routes provide some of the most basic infrastructure for server applications. Read [Express' official introduction to routes](https://expressjs.com/en/starter/basic-routing.html) for context.

{% embed url="<https://expressjs.com/en/starter/basic-routing.html>" %}
Official Express introduction to routes
{% endembed %}

```javascript
// Define a route and corresponding middleware function
app.get("/", (req, res) => {
  res.send("Hello, World!");
});
```

In the above example, our route middleware defines how our server responds to GET requests to the root route `/`. Express applications typically have many routes that serve requests with various HTTP methods to many URL paths. We can handle other request methods by changing `.get` to `.post`, `.put` or `.delete`, and we can handle requests to other paths by changing the path parameter that is currently `'/'`. We can change how our server responds to specific requests by changing logic in the middleware function, for example to query a database and return results. More on databases in coming submodules.

Read [Express' official routing guide](https://expressjs.com/en/guide/routing.html) for a full introduction to Express routes, including how to use the `express.Router` class to decompose our routes into router modules for clearer organisation and abstraction.

{% embed url="<https://expressjs.com/en/guide/routing.html>" %}
Official Express routing guide
{% endembed %}

{% hint style="info" %}
**Require vs Import Statements**

You may notice that Express docs use `require` syntax to import modules. This is an older import syntax that is still supported by Node.js. Luckily we can generally use `require` and `import` statements interchangeably.

Require (aka CommonJS) syntax:

```javascript
const express = require("express");
```

Import (aka ES Modules) syntax:

```javascript
import express from "express";
```

{% endhint %}

## Express Request Extras

{% embed url="<https://youtu.be/wJdY3Vvp2g0>" %}
HTTP Request Extras
{% endembed %}

Please checkout the finished code in this [repository](https://github.com/rocketacademy/m3_express_repo/tree/simple_express_params), ensure that you're on the `simple_express_params` branch if you want to test out the application on your machine you will need to install the dependencies with the command `npm install` after the installation you can then run the application with the command `node index.js`

## Express Fruit Application

{% embed url="<https://youtu.be/8WLofzPe7zI>" %}
Express Fruit Application
{% endembed %}

Please checkout the finished code in this [repository](https://github.com/rocketacademy/m3_express_repo/tree/crud_handlers), ensure that you're on the `crud_handlers` branch if you want to test out the application on your machine you will need to install the dependencies with the command `npm install` after the installation you can then run the application with the command `node index.js`

## Middleware

Middleware functions (aka "middleware") are functions that run during the "request-response cycle" and have access to Express request and response objects. The request-response cycle is the logic a server executes between when the server receives a request and when the server sends a response for that request. Routing methods of the format `app.<METHOD>` are 1 form of middleware.

We can run other non-routing middleware in the request-response cycle by attaching middleware functions with `app.use` before routing middleware. This will allow us to execute arbitrary logic using `req` and `res` objects before our routes, such as logging requests, adding metadata to our requests or validating authentication. Express executes middleware in the order the middleware is bound to the `app` object, until any middleware sends a response back to the client.c

{% code title="index.js" %}

```javascript
const express = require('express');
const app = express();

// Define a custom middleware function myLogger to log requests
const myLogger = function (req, res, next) {
  console.log("LOGGED");
  // Call the next parameter to trigger the next middleware
  next();
}

// Attach myLogger to app with app.use before routes below
app.use(myLogger);

// Attach routes after attaching any non-route middleware
app.get("/", (req, res) => {
  res.send("Hello, World!")
});

app.listen(3000);
```

{% endcode %}

Notice in the above code we attach non-route middleware above route middleware because route middleware typically terminates the request-response cycle by calling [response methods](https://expressjs.com/en/guide/routing.html#response-methods) like `res.send`.&#x20;

Also notice how `myLogger` calls `next()` at the end of its execution to trigger the next middleware. Without calling `next()` the client would never receive a response because Express would not call the subsequent middleware function.

Read [Express' official guide to writing middleware](https://expressjs.com/en/guide/writing-middleware.html) for details.

{% embed url="<https://expressjs.com/en/guide/writing-middleware.html>" %}
Official Express guide to writing middleware
{% endembed %}

Read [Express' official guide to using middleware](https://expressjs.com/en/guide/using-middleware.html) for details on how to use middleware in Express apps, including how to apply middleware on Express routers and how to apply imported 3rd-party middleware, which we will do often.

{% embed url="<https://expressjs.com/en/guide/using-middleware.html>" %}
Official Express guide to using middleware
{% endembed %}

## Express In-Built Middleware

{% embed url="<https://youtu.be/25XpyTTnt58>" %}
Express Middleware
{% endembed %}

Please checkout the finished code in this [repository](https://github.com/rocketacademy/m3_express_repo/tree/built_in_middleware), ensure that you're on the `built_in_middleware` branch if you want to test out the application on your machine you will need to install the dependencies with the command `npm install` after the installation you can then run the application with the command `node index.js`

## CORS

CORS (Cross-Origin Resource Sharing) is a security mechanism that allows servers to specify which domains other than their own to accept requests from. Without CORS, hackers at malicious websites could induce users to perform sensitive actions to manipulate legitimate backends using authentication information stored in the browser. With CORS, legitimate backends can prevent such attacks by only allowing requests from legitimate domains.

CORS is relevant for us now because we will host our frontends and backends on different domains, and we will need to configure our backends to allow requests from our frontends. Express provides an [official CORS middleware NPM library `cors`](https://expressjs.com/en/resources/middleware/cors.html) to configure CORS for our backends.

For now we will use the most open and least secure `cors` configuration (`app.use(cors());`) to get our apps working. There are many ways to configure Express' `cors` library to be most secure that we can learn about later.

## Express Structure

If you find that your backend index.js is getting rather long due to the amount of route handlers, middleware or other code that is implemented. We suggest that you apply some backend structure to your Express directories.&#x20;

{% embed url="<https://youtu.be/J_YBGjBVBYs>" %}
Implementing an Express Router
{% endembed %}

{% embed url="<https://youtu.be/Bj0jYeJS-ZM>" %}
Implementing an Express Controller
{% endembed %}

{% embed url="<https://youtu.be/CRhOv8mtdC4>" %}
Implementing Router and Controller
{% endembed %}

Please checkout the finished code in this [repository](https://github.com/rocketacademy/m3_express_repo/tree/router_and_controller), ensure that you're on the `router_and_controller` branch if you want to test out the application on your machine you will need to install the dependencies with the command `npm install` after the installation you can then run the application with the command `node index.js`

Does the class based code look unfamiliar have a look at the [Rocket curriculum](https://bootcamp.rocketacademy.co/0-foundations/0.4-javascript/0.4.4-classes) to touch up your understanding.

## Additional Resources

1. [Web Dev Simplified's intro to Express](https://youtu.be/lY6icfhap2o) provides a video tutorial to the above Express concepts
2. Stackoverflow shares [API server route design best practices](https://stackoverflow.blog/2020/03/02/best-practices-for-rest-api-design/)
3. Portswigger provides a [detailed explanation of CORS](https://portswigger.net/web-security/cors)


# 3.1.1 : MVC

## Introduction

MVC stands for Model View Controller, these represent 3 logical component of web applications. We use the MVC mental model to refactor our code into multiple files and folders. The MVC concept helps us separate concerns in our web apps but does not strictly define what logic goes in which files, because different web frameworks have slightly different connections.

### Example Code for Grocery Application&#x20;

We will give you the steps to develop an example grocery store application that contains a single model. You can find a repository containing the example application [here](https://github.com/rocketacademy/MVC_Grocery_Example).&#x20;

This application is composed of a backend and a frontend, the backend will contain the Model and Controllers while the frontend handles the View.&#x20;

Here are some of the functionalities of the backend of the application.&#x20;

1. Create a consumable GET API that sends a list of the product stored within the database
2. Create a consumable POST API that allows users to add new products into the database
3. Create a consumable GET API that  retrieves a single product from the database

When  using the MVC setup for your application to add a new product into the database through the API,  our applications will preform these actions:

1. The React view captures the users input and sends this data to the controller as a POST request.&#x20;
2. The controller (which is based on the server) will alter the current model (database) to insert the new product into the database.
3. Once the update is completed, the controller retrieves the recently added product and sends it back to the view as a JSON response.&#x20;
4. The view then is able to update its internal state such that the most current information represented in the server model will be rendered onto the screen.&#x20;

## Implementing the Grocery Application

Now let's get our hands dirty and start to develop a grocery application that follows the MVC setup. We are going to need to set up a nodeJs project for our application, with this in mind we will also need to implement Sequelize database, complete with a migration, model and seed file. If you want a refresher, please look at this [material](https://bc.rocketacademy.co/3-backend/3.e-exercises/3.e.2-bigfoot-sql#reference-only-sequelize-setup). You will need to create and alter a .env file so you can protect your sensitive data. [Look here](https://bc.rocketacademy.co/2-full-stack/2.2-advanced-react/2.2.5-environmental-variables) if you want to remember how to use the .env. We will also be setting up the configuration slightly differently so please, follow closely.&#x20;

### Setting up the Backend &#x20;

Firstly, find the place on your machine where you want to develop, and create a directory there. When we are setting up the backend we are developing the Model and Controller of the application. We will be using Reactjs to develop our frontend and View. In this current directory make a new folder named `grocery_back` to store your backend and `cd` into it.&#x20;

### Setting up the Database

Before you attempt to setup the database with the sequelize-cli you will need to ensure your Postgresql server is running.

Windows users run these commands:

```
sudo service postgresql start
```

```
sudo su postgres
```

```
psql postgres
```

Macos, make sure your Postgres application is running.&#x20;

Now you can run these commands to set up your backend:

`npm init -y`

`npm i sequelize pg dotenv`

`npm i -D sequelize-cli`

Next create a new file inside `grocery_back` named .sequelizerc

The purpose of the .sequelizerc is to configure your application's connection to your database as well as setup the CLI such that files are created in the correct directories. If you would like to see the other configurations that are possible look [here](https://sequelize.org/docs/v6/other-topics/migrations/#the-sequelizerc-file). &#x20;

Make the file appear as below:

```javascript
const path = require("path");

module.exports = {
  config: path.resolve("config", "database.js"),
  "models-path": path.resolve("db", "models"),
  "seeders-path": path.resolve("db", "seeders"),
  "migrations-path": path.resolve("db", "migrations"),
};
```

Within the `grocery_back` directory run the command:

`npx sequelize init`

The db folder that is generated will contain these folders:

* `config`, contains config file, which tells CLI how to connect with database
* `models`, contains all models for your project
* `migrations`, contains all migration files
* `seeders`, contains all seed files

Alter the database.js that is stored within the config folder. You will need to reference the .env that you setup earlier in this file.&#x20;

The database.js should look like below:

{% code title="db/config/database.js" %}

```javascript
require("dotenv").config();

module.exports = {
  development: {
    username: process.env.DB_USERNAME,
    password: process.env.DB_PASSWORD,
    database: process.env.DB_NAME,
    host: process.env.DB_HOST,
    dialect: process.env.DB_DIALECT,
  },
};
```

{% endcode %}

Now you can actually create your database, we will need to set up migrations, models and seeds before we can interact with a real database.&#x20;

At this stage we can create a database within the  `grocery_back`  directory run this command:

`npx sequelize db:create`

### &#x20;Create Database Migrations:

New let's set up our migration file which will be used to create our table in Sequelize. Within the  `grocery_back` directory run this command:

`npx sequelize migration:generate --name products`

The command above should create a new migration file within the db directory, inside the migration folder, `db/migrations/...`. Edit the newly generated file so it looks like below:

{% code title="" %}

```javascript
"use strict";

module.exports = {
  async up(queryInterface, Sequelize) {
    await queryInterface.createTable("products", {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER,
      },
      name: {
        type: Sequelize.STRING,
      },
      price: {
        type: Sequelize.INTEGER,
      },
      created_at: {
        type: Sequelize.DATE,
        allowNull: false,
      },
      updated_at: {
        type: Sequelize.DATE,
        allowNull: false,
      },
    });
  },

  async down(queryInterface, Sequelize) {
    await queryInterface.dropTable("products");
  },
};
```

{% endcode %}

After completing this set up we will be able to run our migration file and create a table within our database, within the  `grocery_back`  directory run this command:

`npx sequelize db:migrate`

After running our migration we should develop our product model, which will enable our controller to easily interface with the data stored within the table.&#x20;

### Create Database Model:

Create a file named product.js within the `db/models` folder.&#x20;

The product.js file should look similar to below:

{% code title="db/models/product.js" %}

```javascript
"use strict";

const { Model } = require("sequelize");
module.exports = (sequelize, DataTypes) => {
  class Product extends Model {}
  Product.init(
    {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: DataTypes.INTEGER,
      },
      name: {
        type: DataTypes.STRING,
      },
      price: {
        type: DataTypes.INTEGER,
      },
      createdAt: {
        type: DataTypes.DATE,
        allowNull: false,
        defaultValue: new Date(),
      },
      updatedAt: {
        type: DataTypes.DATE,
        allowNull: false,
        defaultValue: new Date(),
      },
    },
    {
      sequelize,
      modelName: "product",
      underscored: true,
    }
  );
  return Product;
};
```

{% endcode %}

We will also need to make sure that we have an index.js that will be used to process all of your models and give their Sequelize context to the application.&#x20;

The index.js will need to be within the models directory that should be implemented as below:

{% code title="db/models/index.js" %}

```javascript
"use strict";

const fs = require("fs");
const path = require("path");
const Sequelize = require("sequelize");
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || "development";
const config = require("../../config/database.js")[env];
const db = {};

let sequelize;
if (config.use_env_variable) {
  sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
  sequelize = new Sequelize(
    config.database,
    config.username,
    config.password,
    config
  );
}

fs.readdirSync(__dirname)
  .filter((file) => {
    return (
      file.indexOf(".") !== 0 && file !== basename && file.slice(-3) === ".js"
    );
  })
  .forEach((file) => {
    const model = require(path.join(__dirname, file))(
      sequelize,
      Sequelize.DataTypes
    );
    db[model.name] = model;
  });

Object.keys(db).forEach((modelName) => {
  if (db[modelName].associate) {
    db[modelName].associate(db);
  }
});

db.sequelize = sequelize;
db.Sequelize = Sequelize;

module.exports = db;
```

{% endcode %}

Now that we have developed our Model, for product we can create our seed file to help populate our database. Within the  `grocery_back`  directory run the command below:

### Create Database Seeders:

`npx sequelize seed:generate --name products`

The command above should create a new seed file within the folder `db/seeders/`, we will use this file to create some sample data for the application.&#x20;

Edit the newly generated file so that it looks like below:

```javascript
"use strict";

module.exports = {
  async up(queryInterface, Sequelize) {
    await queryInterface.bulkInsert("products", [
      {
        name: "Doritos",
        price: 15,
        created_at: new Date(),
        updated_at: new Date(),
      },
      {
        name: "Banana",
        price: 10,
        created_at: new Date(),
        updated_at: new Date(),
      },
      {
        name: "Apple",
        price: 10,
        created_at: new Date(),
        updated_at: new Date(),
      },
      {
        name: "Iphone",
        price: 11500,
        created_at: new Date(),
        updated_at: new Date(),
      },
      {
        name: "Cheese",
        price: 50,
        created_at: new Date(),
        updated_at: new Date(),
      },
    ]);
  },

  async down(queryInterface, Sequelize) {
    await queryInterface.bulkDelete("products", null, {});
  },
};
```

After completing this set up we will be able to run our seeder file and populate our product table within our database, within the  `grocery_back`  directory run this command:

`npx sequelize db:seed:all`

Now that we have setup and populated our database we will need to develop an express server that can interact with it.&#x20;

#### <mark style="color:red;">Note</mark>

The code below will implement classes within our applications. If it looks unfamiliar have a look at the [Rocket curriculum](https://bc.rocketacademy.co/0-foundations/0.4-javascript/0.4.4-classes) to touch up your understanding.

### Setting up Routes:

We should develop router files to keep HTTP method and URL path matching outside of the index.js. In this current project we will develop one router file, but generally every router and controller refer to a single type of data stored in your database. In this case we only have a product so only the product router and controller are required.&#x20;

ProductRouter.js is a file that will bind the controller methods such that they are given the express http request and response context. Meaning we can link an API call to our controller to update our database.&#x20;

Please create a Routers directory in the  `grocery_back` directory and create a ProductRouter.js file within, it should be similar to the code below:

{% code title="/Routers/ProductRouter.js" %}

```javascript
class ProductsRouter {
  constructor(express, controller) {
    this.express = express;
    this.controller = controller;
  }

  routes() {
    const router = this.express.Router();

    router.get("/", this.controller.getAll.bind(this.controller));
    router.get("/:productId", this.controller.getOne.bind(this.controller));
    router.post("/", this.controller.insertOne.bind(this.controller));
    return router;
  }
}

module.exports = ProductsRouter;

```

{% endcode %}

### Setting Up Controllers:

At this point in development we have setup our database, and express application with routes. Now we need to develop the controller linked up to the API routes defined above. Lets develop some controller methods to handle our requests and send back proper responses.&#x20;

Each feature or data source can have its own controller. Create a new folder inside the  `grocery_back` directory  named Controllers, create two files within this folder, named ProductController.js and BaseController.js.

We will setup the BaseController.js first as we will be creating a class template that can be used for every subsequent controller we need to develop. Please make the file similar to the code below:

{% code title="/Controllers/BaseController.js" %}

```javascript
class BaseController {
  constructor(model) {
    this.model = model;
  }

  async getAll(req, res) {
    console.log(this.model);
    try {
      const output = await this.model.findAll();
      return res.json(output);
    } catch (err) {
      console.log(err);
      return res.status(400).json({ error: true, msg: err });
    }
  }
}

module.exports = BaseController;
```

{% endcode %}

We can model the ProductsController class on the BaseController class, please implement the file ProductsController.js as below:

{% code title="/Controllers/ProductsController.js" %}

```javascript
const BaseController = require("./baseController");

class ProductsController extends BaseController {
  constructor(model) {
    super(model);
  }

  async insertOne(req, res) {
    const { name, price } = req.body;
    try {
      const newProduct = await this.model.create({
        updated_at: new Date(),
        created_at: new Date(),
        name: name,
        price: price,
      });
      return res.json(newProduct);
    } catch (err) {
      return res.status(400).json({ error: true, msg: err });
    }
  }

  async getOne(req, res) {
    const id = req.params.productId;
    try {
      const output = await this.model.findByPk(id);
      return res.json(output);
    } catch (err) {
      console.log(err);
      return res.status(400).json({ error: true, msg: err });
    }
  }
}

module.exports = ProductsController;

```

{% endcode %}

### Setup Express Js Server:

Ensure that your CLI is within the  `grocery_back` directory and run this command:

`npm i express cors`

This will install the packages, `express` and `cors`, express will be used to power our application and cors is used to facilitate communication between our front and backend.&#x20;

Lets make a new file within the  `grocery_back`  directory named `index.js` the document should be as below:

{% code title="index.js" %}

```javascript
const express = require("express");
const cors = require("cors");
require("dotenv").config();

const db = require("./db/models/index");
const { product } = db;

const ProductsRouter = require("./routers/productsRouter");
const ProductsController = require("./controllers/productsController");

const PORT = process.env.PORT || 3000;

const app = express();

const productsController = new ProductsController(product);
const productsRouter = new ProductsRouter(express, productsController).routes();

app.use(cors());
app.use(express.json());

app.use("/products", productsRouter);

app.listen(PORT, () => {
  console.log("Application listening to port 3000");
});

```

{% endcode %}

As you can see from the file above we still need to implement a few files in order to make our MVC application work. We will define a router system as well as a Controller within our express application. We try to reduce the size of the index.js, only initialising what is required and implementing middleware. This file structure enables multiple developers to work concurrently with minimal interference. If we require additional middleware like auth middleware we can import it and bind it to the application within the index.js.&#x20;

### Running Backend Application

Provided the you have installed all of the required dependencies and you have implemented the backend of this application by following the steps above, we should be able to run the application, from the  `grocery_back`  directory, run this command:

`nodemon index.js`

OR (if you don't have nodemon installed

`node index.js`

You can test your 'Model' and 'Controller' by using [ThunderClient](https://bootcamp.rocketacademy.co/2-full-stack/2.1-internet-101/2.1.2-http-requests-and-responses#thunder-client), please test out your routes and ensure you can send and retrieve data from your database before moving to the next section. \
To test out the GET request we need to fire off a request to the URL <http://localhost:3000/products>, this will respond with a list of all of the products from the backend. It is able to do this because the route handler fires off the getAll method within the controller and returns the data which is sent back to the client, in this case ThunderClient.\
In order to test out the POST request you need to alter the request within ThunderClient to send a POST request not a GET request. We can do this at the top of the window, with this in mind as the POST request is mocking a form submission we will need to attach the form data you can use a JSON object to achieve this. Remember that the data you add will interface with your database and thus the data's keys need to match column names. When ThunderClient sends this request the insertOne method within the controller is fired off, adding a new fruit into the database, that being said, the response is the newly updated products list.&#x20;

### Model

The Model logical component in the MVC refers to the structure of data in our application, and is the component responsible for manipulating data in the database. In this Coding Bootcamp we will use the Sequelize library to power our model architecture, though it should be noted business logic is tired to the controller.  ‘Model’ in MVC refers to the structure of data, as well as how it is stored and queried. Other non-sql database have a variation of Sequelize's model that is used to query tables and data.

### View

View refers to application UI. We’ve already defined views in the ‘views’ folder with JS files. MVC distinguishes between “view logic” and “application logic”. View logic determines how data should be rendered and formatted, e.g. transforming data format without changing the underlying value. Application logic determines how data should be calculated and stored. Views typically contain view logic, and controllers typically contain application logic. We are already developing the frontend of our applications, using the Create-React-App, which is our 'View' within the MVC model.&#x20;

The following are examples of view logic.

1. Uppercasing a post title
2. Shortening post content to fit into a table
3. Transforming a boolean value in the database to a contextual visual element, for example a heart icon for where a user has liked a post.&#x20;

### Controller

Controller refers to the business logic. Controllers are the glue between the model and view, and handle HTTP requests and responses. For example, a controller would determine if, when and how an app would respond with a 404 error message. In Bootcamp, controllers will contain the majority of out applications business logic, and generally everything not a model or view will go into a controller.&#x20;

### Routes

Other than model, views and controllers, we will also develop a router file or files that only connect requests to controllers via the requests’ HTTP method and URL path. This is what we have been doing with methods such as `app.get` and `app.post`. We can imagine route files as a directory of our server’s response logic.

### Setting up the React Application

The React application will be representative of the view that we are creating with the MVC application setup, it will communicate with the Controller through the backend server that was created earlier.&#x20;

The frontend React application will consume the  API’s served by the expressJS backend. It will make a GET request to retrieve all of the available products currently stored within the database. The application will allow users to send a POST request that will create a new item within the database.&#x20;

### Generating boilerplate with Create-React-App:

To develop the frontend of this application we will be using Vitejs. Make sure you are in the root of the project directory and not the `grocery_back` directory. Run this command:

```
npm create vite@latest
```

You will then be prompted for a name, we will call it `grocery_front`. Then choose `React`, then choose `JavaScript`, now follow the rest of the setup commands.&#x20;

Following this install `axios`.&#x20;

This will create a new React application on your machine within the `grocery_front` directory. We will need to alter files within this directory to implement our View.&#x20;

### Creating your View:

Let's first alter the App.jsx that is stored within the src directory. Make the file appear as below:&#x20;

{% code title="/src/App.js" %}

```javascript
import logo from "/logo.png";
import "./App.css";
import AddProduct from "./Components/AddProduct";
import SingleProduct from "./Components/SingleProduct";
import axios from "axios";
import { useState, useEffect } from "react";

export default function App() {
  const [openSingle, setOpenSingle] = useState(false);
  const [products, setProducts] = useState([]);
  const [currentId, setCurrentId] = useState("");

  const getInitialData = async () => {
    let initialAPICall = await axios.get(
      `${process.env.REACT_APP_API_SERVER}/products`
    );
    setProducts(initialAPICall.data);
  };

  useEffect(() => {
    getInitialData();
  }, []);

  const toggleView = (product) => {
    setOpenSingle(!openSingle);
    setCurrentId(product.id);
  };

  const createNewProduct = async (name, price) => {
    let product = {
      name,
      price,
    };
    let response = await axios.post(
      `${process.env.REACT_APP_API_SERVER}/products`,
      product
    );
    let newArray = [...products];
    newArray.push(response.data);
    setProducts(newArray);
  };

  return (
    <div className="App">
      <header className="App-header">
        {openSingle ? (
          <div>
            <SingleProduct toggle={toggleView} id={currentId} />
          </div>
        ) : (
          <div>
            <img src={logo} className="logo" alt="logo" />
            <h3>Grocery Store</h3>
            <h6>Products</h6>
            <div className="products-container">
              {products && products.length > 0 ? (
                products.map((product) => (
                  <div
                    className="product"
                    key={product.id}
                    onClick={() => toggleView(product)}
                  >
                    <h4>{product.name}</h4>
                    <h5>${product.price}</h5>
                  </div>
                ))
              ) : (
                <p>Failure</p>
              )}
            </div>
            <AddProduct addProduct={createNewProduct} />
          </div>
        )}
      </header>
    </div>
  );
}
```

{% endcode %}

Next create a Components folder within the src directory.

Inside this directory create two files, AddProduct.jsx and SingleProduct.jsx

Make the AddProduct.jsx appear as below:

{% code title="/src/Components/AddProduct.jsx" %}

```javascript
import { useState } from "react";

export default function AddProduct(props) {
  const [name, setName] = useState("");
  const [price, setPrice] = useState(1);

  const submit = () => {
    props.addProduct(name, price);
    setName("");
    setPrice("");
  };

  return (
    <div>
      <h3>Add Product Form</h3>
      <label>Product Name:</label>
      <br />
      <input
        type="text"
        value={name}
        placeholder="Add in product name"
        onChange={(e) => setName(e.target.value)}
      />
      <br />
      <label>Product Price:</label>
      <br />
      <input
        type="number"
        onChange={(e) => setPrice(e.target.value)}
        value={price}
      />
      <br />
      <button onClick={submit}>Add Product</button>
    </div>
  );
}

```

{% endcode %}

Now make the SingleProduct.jsx appear as below:

{% code title="/src/Components/SingleProduct.jsx" %}

```javascript
import React from "react";
import { useState, useEffect } from "react";
import axios from "axios";

export default function SingleProduct(props) {
  const [product, setProduct] = useState({});

  const getProduct = async () => {
    let response = await axios.get(
      `${process.env.REACT_APP_API_SERVER}/products/${props.id}`
    );
    setProduct(response.data);
  };

  useEffect(() => {
    getProduct();
  }, []);

  return (
    <>
      <h1>Single</h1>
      <h2>{product.name}</h2>
      <h3>{product.price}</h3>
      <button onClick={() => props.toggle(product)}>Go Back</button>
    </>
  );
}
```

{% endcode %}

We will also need to create a .env file that will be stored within the folder `grocery_front`. It should appear as below:

{% code title=".env" %}

```
VITE_SOME_API_SERVER=http://localhost:3000
```

{% endcode %}

### Running your React Application

At this stage you should be able to run your frontend react application. Run the command within grocery\_front directory:

`npm run dev`

You need to open a browser of your choice and navigate to `http://localhost:5173`.

You should see the project open itself within your default browser, you should be able to add a product as well as click into a single product.&#x20;

## Exercise

Implement the project above, once you understand how it works and you've run both the frontend and backend add in some additional features.

On the frontend, in the SingleProduct Component make it so you can edit the selected item's name or price, capture user input and send an API request. In the App.jsx make it so you can delete an item from the frontend, send an API request to alter the 'model'.

To add additional consumable API's you will also need to set up new methods within the controller as well as new routes in the router.&#x20;

## Fruit Application Controller Creation

{% embed url="<https://youtu.be/ci80xB97L3o>" %}
Sequelize and Controllers (1)
{% endembed %}

{% embed url="<https://youtu.be/0j2fZqhRX4M>" %}
Sequelize and Controller (2)
{% endembed %}

## Testing Fruit Application with Thunder Client

{% embed url="<https://youtu.be/q_9qjLDU84A>" %}
Testing Application (1)
{% endembed %}

{% embed url="<https://youtu.be/CuuZylrvScU>" %}
Testing Application (2)
{% endembed %}

Please checkout the finished code in this [repository](https://github.com/rocketacademy/m3_sequelize_repo/tree/sequelize_controller), ensure that you're on the `sequelize_controller` branch. To test out this repo, you will need to setup your `.env`, install the required dependencies with `npm install`,  then run all migrations and seeders such that you can run the application while its connected to your local database. Then you can run `node index.js .`

## Building Fruit Application Frontend (Legacy CRA)&#x20;

{% embed url="<https://youtu.be/zmsso0wTwVU>" %}
Create React App Fruit Application
{% endembed %}

{% embed url="<https://youtu.be/l7GMh-mXgts>" %}
React Componnets: Fruit && FruitCard
{% endembed %}

{% embed url="<https://youtu.be/nzxAOJl75xo>" %}
Calling API and adding CORS to backend
{% endembed %}

{% embed url="<https://youtu.be/Hs0OSkVNJ04>" %}
Frontend Form Component
{% endembed %}

{% embed url="<https://youtu.be/Y13ydLgeKRs>" %}
Finsihing Frontend Form Component
{% endembed %}

{% embed url="<https://youtu.be/mGnnamK6RTI>" %}
Testing Application and Framing Challenge&#x20;
{% endembed %}

Please checkout the finished frontend code in this [repository](https://github.com/rocketacademy/3.2_react_repo), ensure that you're on the `main` branch if you want to test the code on your machine you will need to install the dependencies with the command `npm install` after the installation you can run the application with `npm run dev`. To test it with a backend please checkout this [repository](https://github.com/rocketacademy/m3_sequelize_repo/tree/cors), ensure that you're on the `cors` branch if you want to test the code on your machine you will need to install the dependencies with the command `npm install` after the installation, then implement you `.env.` If you've not setup the database previously, run your migrations and seeders and once this is completed you can run the application with `node index.js`.&#x20;


# 3.2: SQL

## Learning Objectives

1. SQL is a robust, mature and the most popular query language for relational databases
2. Understand basic SQL commands
3. PostgreSQL is a popular SQL dialect and database server application
4. \[Nested submodules] Understand 1-M and M-M SQL relationships and corresponding table structures
5. \[Nested submodules] Understand how to set up a SQL database with a backend API server
6. \[Nested submodules] Understand how to design SQL database schemas for different business applications

## Introduction

SQL (Structured Query Language) is a robust, mature and the most popular query language for relational databases. We use SQL to store, manage, and retrieve data from relational databases, aka SQL databases.

A relational database is a database composed of "relations", also known as tables. Tables are like spreadsheet tables with headers in the first row, each identifying the data that will be in its respective column.&#x20;

A primary strength of relational databases is their ability to represent relationships in data. For example, in a social media app I might have a `users` table and a `posts` table, and a relational database would be able to represent that each post belongs to a user, and that a user has many posts.

## PostgreSQL

PostgreSQL (aka "Postgres") is a popular and robust SQL dialect that is both lightweight and feature-rich. Other popular SQL dialects include MySQL (heavy, feature-rich) and SQLite (light, less feature-rich).

Postgres is also a database server application that we will use to store and retrieve data for our apps using the Postgres language. Postgres is typically run on its own server in production for modularity (multiple apps may want to access this DB) and security (different security rules for our DB vs API server).

## Intro to Database Servers

Database servers run applications that allow programs to manipulate the data inside them. In this module we'll learn how to create, manage, and deploy database servers. Note that this is separate from managing the *data* inside the database, which is done by the SQL language. How SQL interacts with the database server hard drive depends on the particular SQL implementation.

Part of setting up a database is setting up database schema, i.e. what tables and columns are in the database. Web applications typically do not manipulate database schema in response to user actions; application code depends on database schema, but the schema is not defined by the application.

![The data in the database is stored separately from the application code](/files/lLPC5NWZP5BMYBRWSa9t)

Unlike with the `data.json` file we used prior to SQL, the data inside our database will *not* be part of the application repo. Database servers are often on separate machines from web application servers, such that they can be accessed by multiple applications. We will see this when we use Heroku, but for now, we will keep our database server on the same machine as our Express app.

![The PostgreSQL server is typically on a separate machine from the web application that accesses it. ](/files/RuVZtCletz7SeIb7DaVZ)

Managing the database server application, e.g. ports, backups, version upgrades, is typically considered developer operations or DevOps and can be a separate role from application development.

## Intro to PostgreSQL

Postgres implements the SQL language in order to store and retrieve data from a set of files on the hard drive.

Postgres is a server application that uses its own TCP/IP protocol, usually on port 5432 (although this is configurable). Requests are sent to the server that contain the SQL language queries for the server to process. The result of the queries is sent back to the client.

Postgres is a software implementation of a database system. So far we've only dealt with a database at a conceptual level, and using that database though SQL.

However, a database system is the actual implementation of something that runs SQL and keeps the data. Each system implements the SQL language slightly differently, keeps the data on the disk in a slightly different way, and gets the data back out differently.

The database system ensures fundamental database properties like [ACID](https://en.wikipedia.org/wiki/ACID) (atomicity, consistency, isolation, durability). A database system needs to account for circumstances like when two opposing queries happen at the same time, or like when a long running INSERT query fails while executing, due to something like power failure. The system doesn't solve these problems, but it is guaranteed to behave in a consistent manner each time.

A database system also includes functionality like automatic data backup and database indexes for increasing query speed.

## psql setup

psql is the Postgres command-line client to access our databases. To help us learn SQL we will use `psql` to manipulate our databases with SQL commands. In later modules we will use a SQL client that allows us to manipulate our databases using a GUI.

### Mac

Install [postgres.app](https://postgresapp.com). Open the application and follow the setup instructions on the website. Do the optional step to configure `$PATH` to use included command line tools.

{% embed url="<https://youtu.be/cEOe6WRAhRE>" %}
Installing Postgres Mac
{% endembed %}

### Ubuntu (for Windows users in WSL and EC2 Installation)

Install Postgres

```
sudo apt update
sudo apt upgrade
sudo apt install postgresql
sudo apt install postgresql-client
```

Set the Postgres server to start in the background:

```
sudo service postgresql start
```

Set password-less login by opening pg\_hba.conf and copying the below contents into it.&#x20;

<mark style="color:red;">**Note**</mark>

The command below assumes you've installed postgresql version 12, **you may need to alter the commands to accommodate a newer version of postgres** depending on which version you've installed.

```bash
// Postgres Version 12
sudo chmod 777 /etc/postgresql/12/main/pg_hba.conf

// Postgres Version 14
sudo chmod 777 /etc/postgresql/14/main/pg_hba.conf
```

```bash
# "sudo" runs the command as the root user
# "$(which code)" gets the location of the VSCode application locally

sudo "$(which code)" /etc/postgresql/12/main/pg_hba.conf
```

If the above command doesn't work, try running VSCode without `sudo`.

For the next command to work you will need to have the code command installed on your machine.

```bash
# Open pg_hba.conf in VSCode

// Postgres Version 12
code /etc/postgresql/12/main/pg_hba.conf
```

The above will open a new VSCode window.

`pg_hba.conf` contents to copy: (replace the whole file contents with the lines below)

```
# TYPE  DATABASE        USER            ADDRESS                 METHOD

# IPv4 local connections:
local    all            all                                     trust
host     all            all             127.0.0.1/32            trust
# IPv6 local connections:
host     all            all             ::1/128                 trust
```

Restart Postgres to get the new configs:

```
sudo service postgresql restart
```

Login as the user `postgres` - the default root user for the Postgres database. This system user was created when you installed Postgres.

```
sudo su postgres
psql postgres
```

## Basic SQL Commands

When creating your database within PostgreSQL you will need to be armed with some knowledge, namely the ability to create tables, insert information and subsequently query that dataset. In this section we will explore how we can interface with our database through the command line interface.

#### Starting PostgreSQL (Mac)

The first step is to start your PostgreSQL server and open a CLI window. For Mac users goto the applications toolbar and find this logo:

<figure><img src="/files/MsQaoIwkhIQq9htYaxZI" alt=""><figcaption><p>PostgreSQL logo</p></figcaption></figure>

Click on it, it will start up the PostgreSQL server and it will open a window that is similar to below, you may need to click start on when selecting a Postgres instance:

<figure><img src="/files/fjzDOCmqMmvZ0HCoguwE" alt=""><figcaption><p>PostgreSQL Mac GUI</p></figcaption></figure>

From this panel select a database, here we have highlighted the fruit database, once you click on it a terminal window will appear:

<figure><img src="/files/CfY757kTVfYpVXrlsYoy" alt=""><figcaption><p>PostgreSQL terminal window</p></figcaption></figure>

From this window we can interface with Postgres using SQL as well as PostgreSQL commands. We are currently accessing the fruit database and will only be able to query tables within that database from here.&#x20;

#### Starting PostgreSQL (Ubuntu - Windows)

To interface with PostgreSQL through your command line (Ubuntu) first open a new Ubuntu instance, then execute these commands:

```
sudo service postgresql start
sudo su postgres
psql postgres
```

In both Mac and Windows what we are doing is starting the PostgreSQL server on our computer, then we are making a connection to a particular database on the server. The commands above first start the PostgreSQL service, specifies that we are running PostgreSQL commands and then connects to the default PostgreSQL database.

#### Making your user

Create a user and database named after your Ubuntu user.&#x20;

Use the Postgres `CRATE USER` command to create a new Postgres database user that is named the same as your current user.

```
CREATE USER <my_user> WITH SUPERUSER CREATEDB CREATEROLE LOGIN;
```

Create a default Postgres database named after your current user. We will use DBs named after our usernames to test SQL syntax. Once we start building applications with SQL, we will name our DBs after our applications.

```
CREATE DATABASE <my_user>;
```

#### Common PostgreSQL commands

When you have connected to a PostgreSQL database you can easily list all of your databases, users or current tables:

List all of the databases on this PostgreSQL server:

```
\l
```

When you run this command in the current window you will get a table that contains all of the current databases and pertinent information regarding it.

Change the current window to another database:

```
\c <db-name>

// example command below

\c samoshaughnessy
```

The command above would change the current window to another database, in this case one named samoshaughnessy, this users database.

Another useful command is to list out all of the tables within the current database context.

```
\dt
```

The command above will generate a table which contains information about each table.

To list out all of the users you can use the command below:

```
\du
```

In order to create a new database you can use the command below:

```
CREATE DATABASE new_database;
```

You can alter the name of the databases by chnage the value `new_database` to your desired database name.&#x20;

#### Creating a table

After connecting to the appropriate database we can use the CREATE TABLE statement to develop a new table within the database. In the example below we will create a new table named students that contains a few columns regarding student information. Try to create this table within the users database.

```sql
CREATE TABLE students (
    id SERIAL PRIMARY KEY,
    first_name VARCHAR(255),
    last_name VARCHAR(255),
    mobile INT,
    gender BOOLEAN
    );
    
```

This command generates a table that contains five columns, an auto-incrementing identity column, id, two character columns first\_name, last\_name. This is followed by two additional columns mobile and gender which have the datatype of integer and boolean respectively. We are generating columns by naming the column, then adding a datatype with any column constraints that we need to implement. You can alter the datatype and constraints by changing the arguments to the code above. To see what PostgreSQL datatypes you can insert please checkout [this documentation](https://www.postgresql.org/docs/current/datatype.html). If you want to checkout the constraints [click here](https://www.postgresql.org/docs/current/ddl-constraints.html).

#### <mark style="color:red;">SQL NOTE</mark>

It should be noted that we must end the command with a semicolon otherwise PostgreSQL will not register that the command is complete.

#### Data Insertion

Inserting data into tables is the next step in database creation, the code below demonstrates an insertion query that will add a new row of data into the previously generated student table.

{% code overflow="wrap" %}

```sql
INSERT INTO students (first_name, last_name, mobile, gender) VALUES ('Foong', 'Leung', 9987712, true);
```

{% endcode %}

We entered a new student into the database, notice how we didn't need to insert an id, this is due to the SERIAL constraint we added when creating our table. These id's act a [Primary Keys](https://www.postgresql.org/docs/15/ddl-constraints.html#DDL-CONSTRAINTS-PRIMARY-KEYS) which are vital unique identifiers for our rows of data. The  information that is required is the data that will be placed in our columns for this row, the two strings, a number and  the final value a boolean, true, true represents male within this table structure.

You can add in additional rows of information one at a time or you can insert multiple values like the command below.

{% code overflow="wrap" %}

```sql
INSERT INTO students (first_name, last_name, mobile, gender) VALUES ('Sam', 'O"Shaughnessy', 2781192, true), ('Neo', 'Yuan', 4366813, true) ;
```

{% endcode %}

#### Data Querying

When working with databases, it is important that you can query information such that you're able to manipulate, retrieve and delete data. You are able to do this from your command line interface and this is the next step in hands on database management. Querying data is dependant on specificity and targeting the correct information. You can select information from a database by table, row or under a condition, we will showcase a few of these commands below.

{% code overflow="wrap" %}

```sql
// Selecting by Table
SELECT * FROM students;
// This will return all of the enteries from the students table

SELECT first_name, last_name FROM students;
// This will return all of the data within the columns first_name and last_name from the students table

// Selecting by Row
SELECT * FROM students WHERE id = 1;
// This will return the row with an id of 1 from the students table

// Selecting by Condition
SELECT * FROM students WHERE gender = false;
// This will return all of the rows where gender is false.
```

{% endcode %}

To alter existing data within the tables you can use the UPDATE or DELETE commands paired with the WHERE claus that we saw in the previous code block. It should be noted that you can use logical operations like greater than or less than, read more about this [here](https://www.postgresql.org/docs/current/functions-comparison.html). Checkout the code block below to see how you can update and remove information inside a table.

{% code overflow="wrap" %}

```sql
// Update a row by ID
UPDATE students SET first_name = 'Neo Kai', mobile = 86739984 WHERE id = 3;

// Update a row by column value
UPDATE students SET first_name = 'Neo Kai', mobile = 86739984 WHERE first_name = 'Neo';

// Deleting data using id
DELETE FROM students WHERE id = 1;

// Deleting data using condition
DELETE FROM students WHERE gender = true; 
```

{% endcode %}

#### SQL relationships&#x20;

Creating tables and inserting data allows you to create some structure for data within your database. To really showcase meaningful information within a database, tables should have relationships and in more complex instances data could depend on other sets. To showcase this we will develop another table student\_addresses.

{% code overflow="wrap" %}

```sql
CREATE TABLE student_addresses (
    id SERIAL PRIMARY KEY,
    student_id INT,
    address VARCHAR(255),
    CONSTRAINT fk_student_id
    FOREIGN KEY (student_id)
    REFERENCES students(id)    
);
```

{% endcode %}

The above command will generate a new table that contains three columns, an id, a student\_id which is referencing data in our students table and our address column. In this instance we have to ensure that data is present within the students table before we can add any data into students\_addresses this is because we are referencing an id within the students table for every entry within student\_addresses. If you want to read more about foreign keys please look into [this set of documentation](https://www.javatpoint.com/postgresql-foreign-key).&#x20;

Once you have developed a database that contains multiple tables that have relationships you will be able to query with what are known as join clauses. Joins allow you to select from multiple tables, the returned information will only return the information that satisfies all of the criteria. To find out more about joins please look into this [set of documentation](https://www.geeksforgeeks.org/sql-join-set-1-inner-left-right-and-full-joins/). Check out the command below:

{% code overflow="wrap" %}

```sql
SELECT * FROM students JOIN student_addresses ON students.id = student_addresses.student_id WHERE gender = false;
```

{% endcode %}

This will produce the most common join the inner join. Which means you will only be returned records that have matching values within both tables. We have also added an additional claus further refining the search to only show the female students who have an address within the students\_addresses table. It should be noted that the returned table that contains our information will not persist and you will need to run the query above to get the data.

## Post-Class Exercises: Codecademy Learn SQL

Complete all exercises in the following Codecademy lessons when they are assigned in the Rocket course schedule.

The following exercises introduce basic SQL syntax. We will not write much SQL during Rocket because we will rely on ORMs (Object-Relational Mappings) such as Sequelize to construct SQL using JavaScript for more robust applications. However, it is relevant to know SQL syntax and some companies test for it during interviews.

1. [Manipulation](https://www.codecademy.com/courses/learn-sql/lessons/manipulation/exercises/sql)
2. [Queries](https://www.codecademy.com/courses/learn-sql/lessons/queries/exercises/queries)
3. [Aggregate Functions](https://www.codecademy.com/courses/learn-sql/lessons/aggregate-functions/exercises/intro)
4. [Multiple Tables](https://www.codecademy.com/courses/learn-sql/lessons/multiple-tables/exercises/intro) (left joins, cross joins, unions and "with" syntax are more niche and less important for Bootcamp, but may be helpful in data analyst work)

## Additional Resources

1. Codecademy SQL cheatsheets for [Manipulation](https://www.codecademy.com/learn/paths/learn-sql/tracks/learn-sql/modules/learn-sql-manipulation/cheatsheet), [Queries](https://www.codecademy.com/learn/paths/learn-sql/tracks/learn-sql/modules/learn-sql-queries/cheatsheet), [Aggregate Functions](https://www.codecademy.com/learn/paths/learn-sql/tracks/learn-sql/modules/learn-sql-aggregate-functions/cheatsheet) and [Multiple Tables](https://www.codecademy.com/learn/paths/learn-sql/tracks/learn-sql/modules/learn-sql-multiple-tables/cheatsheet)
2. [This CS50 video](https://www.youtube.com/watch?v=gu980iXwY5c) explains common SQL syntax
3. [Article on when to choose MySQL vs Postgres](https://developer.okta.com/blog/2019/07/19/mysql-vs-postgres)
4. [ACID properties](https://en.wikipedia.org/wiki/ACID) required of all production databases


# 3.2.1: SQL 1-M Relationships

## Learning Objectives

1. SQL relationships associate data between 1 or more SQL tables to model logical relationships and make data querying more modular and efficient
2. There are 3 kinds of relationships in SQL: one-to-one (1-1), one-to-many (1-M) and many-to-many (M-M)
3. Understand how SQL represents 1-M relationships in its databases

## Introduction

Imagine a social media app with `Users` and `Posts` tables in its SQL database. How would the app know which posts belong to which users? The answer is SQL relationships.

To model the fact that each user can have 0 or more posts, but each post can belong to at most 1 user, we can implement a so-called one-to-many relationship (aka association) between users and posts.

SQL implements relationships using the concept of "primary" and "foreign" keys. Every table has a "primary key" (typically the `id` column) that uniquely identifies each row (aka record, entry) in the table. Tables can have columns that reference primary keys of related tables to define relationships between those tables. Primary keys referenced in other tables are known as "foreign keys", because from the perspective of the tables referencing the primary keys, those keys belongs to "foreign" tables.

The following is a sample `Users` table where `id` is the primary key. There are no foreign keys on this table.

| id (primary key) | username |
| ---------------- | -------- |
| 1                | foong    |
| 2                | kai      |

The following is a sample `Posts` table where `id` is also the primary key, but each post also belongs to a `User`, and specifies a `userId` to identify the user the post belongs to. `userId` is known as a "foreign key", because it references the "primary key" of another table.

| id (primary key) | text                      | userId (foreign key) |
| ---------------- | ------------------------- | -------------------- |
| 1                | "Go Rocket!!!!!!!!!!"     | 1                    |
| 2                | "Rocket is the Best!!!!!" | 1                    |
| 3                | "🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀"    | 2                    |

The foreign key always lives in the "many" table in the one-to-many relationship. In our above example, notice the foreign key lives in the `Posts` table and not the `Users` table, and it cannot be the other way around. If we tried to put a `postId` or `postIds` foreign key in the `Users` table, we would find that we would need to either duplicate `User` rows for each user's posts, or store an array of post IDs in the foreign key column. The former would repeat `User` data unnecessarily, and the latter would make SQL harder to query because of the array structure within a single cell of the table.

The above architecture of SQL relationships makes SQL efficient at storing data. The alternative might be to have a single `Posts` table where we store each `User`'s data repeatedly in every post, but that would be wasteful and inefficient, especially when our `Users` table contains more data such as contact information and preferences.

SQL stores one-to-one relationship data in the same way as one-to-many, except that the foreign key can live in either table. One-to-one relationships are less common because most of the time all the data in one-to-one relationships can be stored in a single table. Like one-to-many relationships, in one-to-one relationships there should only be 1 table with the foreign key. Examples of one-to-one relationships include users and their relevant contact and auth information if we were to separate that information into multiple tables for more efficient querying.&#x20;

## Querying related data using SQL

Given the above `Users` and `Posts` tables, we can query for related data using primary and foreign key relationships.

For example, to query all posts that belong to `kai`, I could run 2 queries. The 1st query retrieves the `id` of the user with username `kai`.

```sql
SELECT id from Users where username='kai';
```

The above query would return `2`, `kai`'s user ID. The 2nd query retrieves the posts that belong to the user with that user ID, and should return all of `kai`'s posts.

```sql
SELECT * from Posts where userId=2;
```

We will not perform such queries with raw SQL in our apps, but we may need to perform such queries when performing analytics on our companies' databases outside of an app context. In our apps we typically use ORMs like Sequelize that make querying for related data more robust, with commands such as `user.getPosts()`. More on querying data with Sequelize in Sequelize submodules.

## Additional Resources

1. [Database normalisation theory](https://en.wikipedia.org/wiki/Database_normalization) suggests ways to structure our SQL database using an optimal number of 1-M and M-M relationships to minimise redundancy. This is especially important for companies processing large volumes of data.
2. If you want to define relationships with pure SQL you should read this [Stack-overflow article](https://stackoverflow.com/questions/7296846/how-to-implement-one-to-one-one-to-many-and-many-to-many-relationships-while-de).

{% embed url="<https://www.youtube.com/watch?v=zsjvFFKOm3c>" %}
SQL in 100 seconds
{% endembed %}


# 3.2.2: SQL M-M Relationships

## Learning Objectives

1. SQL M-M relationships require a junction table between the 2 related tables, where the junction table contains at least both primary keys of the related tables
2. Junction tables can also contain non-foreign-key data columns that store information about the relationship in each row of the junction table

## Introduction

We will now learn to associate data with many-to-many (M-M) relationships, such as sightings and categories, songs and genres, people and personality traits. In each of these pairs, both entities have many of the other entity.&#x20;

So far we have not been able to model M-M relationships because our table structures have limited us. Storing a foreign key on either of the tables in a M-M relationship would limit us, because that would imply that each row in the table with the foreign key could only belong to a single row in the related table. We do not wish to store arrays of foreign keys (or anything) in SQL columns because doing so makes querying less efficient, and we also cannot duplicate rows to specify multiple foreign key values because we cannot have multiple rows with the same ID or primary key.&#x20;

In the following hypothetical `People` table where each person has multiple (up to infinite) personality traits, it is not possible to associate each person with multiple personality traits, assuming each personality trait also belongs to many people.

| id | name  | PersonalityId |
| -- | ----- | ------------- |
| 1  | Joe   | 1             |
| 2  | Sally | 2             |

The solution is what we call a "junction" table, aka "join" or "through" table that sits "in between" the tables with an M-M relationship. This junction table consists minimally of 3 columns: `id` (typically the primary key of the junction table) and 2 foreign keys corresponding to the IDs of the tables with an M-M relationship. The junction table works well because it allows us to specify combinations of each row in both related tables without repeating any unnecessary data.

Imagine the following `People` table.

| id | name  |
| -- | ----- |
| 1  | Joe   |
| 2  | Sally |

Now imagine the following `Personalities` table.

| id | trait           |
| -- | --------------- |
| 1  | Confident       |
| 2  | Detail-oriented |
| 3  | Kind            |

How would we specify that Joe is confident and detail-oriented, and Sally is confident and kind? Similarly, how would we specify that both Joe and Sally are confident? The answer is a junction table like the following.

| id | PersonId | PersonalityId |
| -- | -------- | ------------- |
| 1  | 1        | 1             |
| 2  | 1        | 2             |
| 3  | 2        | 1             |
| 4  | 2        | 3             |

Notice the junction table specifies all associations precisely without repeating any unnecessary data. This is what makes SQL M-M relationships efficient to store and to query.

## Storing and retrieving M-M relationship data with SQL

### Store M-M relationship data

In raw SQL we would insert data into the junction table manually. Assuming the table structures above and that all people and personalities are already in the database, we could write a SQL query like the following to specify that Joe is confident.

```sql
INSERT INTO "PersonPersonalities" ("PersonId", "PersonalityId") VALUES (1, 1);
```

Notice how manual this is and prone to human error if we were to mistype one of the table names, column names or values. This is why SQL is primarily used for querying and not inserting new data from applications.

Notice we have assumed the junction table name is "PersonPersonalities". It is convention to name the junction table after the concatenation of the 2 related table names, where the 1st table in the concatenation is singular and the 2nd is plural. There is no rule for which table should go 1st or 2nd in the concatenation.

### Retrieve M-M relationship data

If I wanted to query for what personality traits Joe has, I would query the junction table for Joe's personality traits.

```sql
SELECT "PersonalityId" FROM "PersonPersonalities" WHERE "PersonId"=1;
```

The above query assumes I already know Joe's `id` is 1, otherwise I would have to first query for Joe's ID. The query retrieves `PersonalityId`s associated with Joe, and I would then need to map these IDs back to personality trait names. It's common in data analysis to use SQL joins to perform this query and the ID-to-name mapping in a single query.

Again, handling IDs manually is tedious and error-prone, hence why we use ORMs like Sequelize in apps.

## Storing and retrieving non-foreign-key relationship data in junction table

### Non-foreign-key data in junction table

A common feature of junction tables is to store additional columns beyond the IDs of the 2 related tables. For example, in our `People` and `Personalities` example, we may wish to store intensity of each personality trait. Even when 2 people are both confident and kind, one might be relatively more or less confident or kind than the other.

To store so-called non-foreign-key relationship data in our junction table, our junction table `PersonPersonalities` could look like the following.

| id | PersonId | PersonalityId | intensity |
| -- | -------- | ------------- | --------- |
| 1  | 1        | 1             | 2         |
| 2  | 1        | 2             | 1         |
| 3  | 2        | 1             | 3         |
| 4  | 2        | 3             | 2         |

Notice the `intensity` column in the above example. We define intensity as a number between 1-3 that represents how intensely this person embodies this personality. Notice how we would not be able to store intensity on either `People` or `Personalities` tables directly because each person does not have the same intensity for each personality, and each personality does not have the same intensity for each person.

The above table tells us Joe has intensity 2 for confidence and intensity 1 for detail-oriented. What about Sally?

### Storing non-foreign-key-data in junction table

Similar to foreign key data, in raw SQL we could query the junction table directly to store non-foreign-key data such as intensity.

```sql
INSERT INTO "PersonPersonalities" ("PersonId", "PersonalityId", intensity) VALUES (1, 1, 2);
```

### Retrieving non-foreign-key data from junction table

Also similar to foreign key data, we can retrieve non-foreign-key data from the junction table directly with SQL.

```sql
SELECT "PersonalityId", intensity FROM "PersonPersonalities" WHERE "PersonId"=1;
```

## Additional Resources

1. [Here is a video](https://youtu.be/1eUn6lsZ7c4) that visually explains the concept of a SQL M-M relationship with a junction table.


# 3.2.3: SQL Schema Design

## Learning Objectives

1. SQL schema design is the process of articulating what SQL tables, columns and relationships we need for a given app's database.
2. Know how to draw an ERD (entity relationship diagram) to visualise SQL tables, columns and relationships
3. Know how to use DrawSQL to draw ERD diagrams

## Introduction

SQL schema design is the process of articulating what SQL tables, columns and relationships we need for a given app's database. There is [extensive theory](https://en.wikipedia.org/wiki/Database_normalization) on how to optimise SQL schemas, but for now we will focus on building simple schemas that solve our problems without worrying too much about theory.

We will follow 3 rules when designing our schema:

1. Every table must have a unique ID column
2. Every cell may only have 1 piece of data. No data structures such as arrays or hash tables.
3. Only IDs can be duplicated in multiple tables via foreign keys. Everything else should be referenced by foreign key.

## Entity Relationship Diagram (ERD)

An entity relationship diagram (ERD) is a diagram that depicts SQL tables, columns and the relationships between them. Apps that use SQL databases typically have database ERDs to help engineers plan ahead. Apps that use NoSQL databases typically also have some form of [schema plan](https://firebase.google.com/docs/database/web/structure-data#flatten_data_structures) but SQL ERDs are more common and standardised.

Below is a sample ERD for Rocket's Bigfoot exercises created with [DrawSQL](https://drawsql.app/).

<figure><img src="/files/9xCQjVmFI1sWsI28ucT3" alt=""><figcaption><p>Database ERD for Rocket's Bigfoot exercises</p></figcaption></figure>

Notice the 3 entities we created for our app: sightings, comments and categories in their respective tables. Notice there is a 4th table `SightingCategories` between `Sightings` and `Categories`; This is the junction table in the M-M relationship. We will always include junction tables in our ERDs even if we do not create models for them in our apps.

Notice the lines between the tables; These represent the relationships between them. Each line represents a relationship, and the ends of the lines communicate whether the relationships are 1-1 or 1-M. 1-1 lines (we don't have any) have no special ends. 1-M lines have a "crow's foot" at the end of the line that touches the "many" table in the 1-M relationship.

Instead of depicting M-M relationships with lines that have crow's feet at both ends, a common practice in ERDs is to split M-M relationships into 2 1-M relationships, like what we did with `Sightings`, `SightingCategories` and `Categories`. This clarifies exactly what tables will be in the database.

Notice how our Bigfoot ERD satisfies our rules above:

1. Every table has a unique `id` column that is its primary key
2. Every cell only has 1 piece of data
3. Only IDs are duplicated across multiple tables as foreign keys; all other data only exists in its own table

## DrawSQL

Rocket recommends we use [DrawSQL](https://drawsql.app/) to create ERDs because of its simple and ERD-specific interface. We can quickly create the tables, columns and relationships we need, and share our ERDs easily with links or images. We will use DrawSQL for upcoming exercises that involve ERDs.

![DrawSQL interface for creating ERDs](/files/CV3Yd6T0QbL8xHN84fcL)


# 3.2.4: Advanced SQL Concepts

## Learning Objectives

1. SQL indexes can increase lookup speed on specific columns in SQL databases by creating a hash-table-like data structure referencing those columns
2. SQL transactions allow us to run either all or none of the queries in a specified series of queries, helping to prevent database corruption

## Introduction

We will likely not need to use SQL transactions and indexes during Rocket's Bootcamp, but these concepts are commonly used in industry especially for larger and more sensitive data. These concepts have appeared often enough in software engineering interviews that we thought it would be relevant to mention them.

## SQL Indexes

SQL indexes can increase lookup speed on specific columns in SQL databases by creating and maintaining a hash-table-like data structure referencing data in those columns. Without SQL indexes, SQL databases often resort to linear search to find the data they need in specific columns. Column data is typically not sorted. As we have learned from algorithms, for large data sets, an `O(1)` lookup speed with a hash table will be significantly faster than an `O(n)` lookup speed with an unsorted array.

Engineers building apps with large SQL databases that query specific columns often may wish to add indexes on those columns. Sequelize docs provide [examples](https://sequelize.org/docs/v6/other-topics/indexes/) and [API references](https://sequelize.org/api/v6/class/src/dialects/abstract/query-interface.js~queryinterface#instance-method-addIndex) for adding indexes on specific columns.&#x20;

Data analysts repeatedly querying specific columns in large SQL databases outside of an app context may wish to add indexes on those columns. [Postgres docs](https://www.postgresql.org/docs/current/indexes-intro.html) explain the motivation and execution of SQL indexes in Postgres databases with raw SQL queries. Creating indexes with raw SQL is helpful for data analysts&#x20;

The drawback of SQL indexes is that they take up space. This is why we do not create SQL indexes on every column by default.

## SQL Transactions

SQL transactions allow us to run either all or none of the SQL queries in a specified series of queries. This prevents database corruption where one or more queries may have succeeded, but one or more may have failed afterward.

For example, banking apps typically use transactions to perform money transfers to prevent situations where money is removed from the source account but not added to the destination account. By putting all transfer operations in a transaction, removing from source and adding to destination either both happen or not at all.

We will not need to use transactions at Rocket. Our Rocket projects likely involve small amounts of non-sensitive data, hence transactions are less important for now. But when we start work with large amounts of live user data, especially financial or healthcare data, data integrity becomes paramount and SQL transactions are a crucial tool.

Sequelize provides a [transactions tutorial](https://sequelize.org/docs/v6/other-topics/transactions/) to learn SQL transactions with Sequelize. Managed transactions should work for most cases, and in cases where we may want more fine-grained control we can use unmanaged transactions. [Postgres also explains](https://www.postgresql.org/docs/current/tutorial-transactions.html) how to use transactions in raw SQL, although we will almost never be updating our databases with raw SQL except in exceptional situations.


# 3.2.5: SQL - Express

## Database Setup

Our node applications will not set up the Database or the tables. Databases and tables need to be created before our applications run. The code in this section assumes that we have set up Postgres, at this point you should have created a Postgres user and be able to enter the DataBase named after the current Unix username. We can retrieve the current Unix username with the `whoami` command in Terminal.

When running the below code, replace `<MY_UNIX_USERNAME>` with your Unix username. We will connected to the users database that we developed in a [previous section](/3-backend/3.2-sql).&#x20;

### pg NPM Library

To use Postgres in Node, we need to install the Postgres client library for node,[ pg](https://www.npmjs.com/package/pg). This enables our application to connect with our database. The command below should be run within an npm initialised directory:

```
npm install pg
```

### DB Queries in Node

#### SELECT

The following Node application runs a SQL query on our `students` table. What does this code do?

<mark style="color:red;">**Replace \<MY\_UNIX\_USERNAME>**</mark>

**index.js**

```javascript
const pg = require('pg');
const { Client } = pg;

// set the way we will connect to the server
const pgConnectionConfigs = {
  user: '<MY_UNIX_USERNAME>',
  host: 'localhost',
  database: '<MY_UNIX_USERNAME>',
  port: 5432, // Postgres server always runs on this port
};

// create the var we'll use
const client = new Client(pgConnectionConfigs);

// make the connection to the server
client.connect();

// create the query done callback
const whenQueryDone = (error, result) => {
  // this error is anything that goes wrong with the query
  if (error) {
    console.log('error', error);
  } else {
    // rows key has the data
    console.log(result.rows);
  }

  // close the connection
  client.end();
};

// write the SQL query
const sqlQuery = 'SELECT * FROM students';

// run the SQL query
client.query(sqlQuery, whenQueryDone);
```

`client.end()` terminates the connection with the SQL client, which is necessary for our Node script to exit. If we do not terminate the SQL connection, the Node script will hang until the connection is terminated.&#x20;

**Command Line**

```
node index.js
```

#### Note

When working in companies you may be asked to mask your database credentials with .env.

#### INSERT

When we replace the SQL query in `index.js` with the following, what does this do?

{% code overflow="wrap" %}

```javascript
const sqlQuery =
  "INSERT INTO students (first_name, last_name, mobile, gender) VALUES ('Eric', 'Marsh', 874480753, true)";
```

{% endcode %}

#### INSERT with value params

We can give structured data to the query. The syntax is slightly different.

Confusingly, SQL syntax here uses an array to pass in the data: `['Eric', 'Marsh', 874480753, true]` then references those array values in the query, `INSERT INTO students(first_name, last_name, mobile, gender) VALUES($1, $2, $3, $4)` but the value `$1` references array index `0`. This is because SQL is a \[1-indexed language]\([https://stackoverflow.com/questions/53631015/why-sql-primary-key-index-begin-at-1-and-not-at-0#:\~:text=3 Answers\&text=Counting in SQL generally starts,1 %28and not 0%29.\&text=We don't start counting at zero until we learn programming](https://stackoverflow.com/questions/53631015/why-sql-primary-key-index-begin-at-1-and-not-at-0#:~:text=3%20Answers\&text=Counting%20in%20SQL%20generally%20starts,1%20%28and%20not%200%29.\&text=We%20don%27t%20start%20counting%20at%20zero%20until%20we%20learn%20programming).), and most other programming languages including JS are 0-indexed.

{% code overflow="wrap" %}

```javascript
const inputData = ['Eric', 'Marsh', 874480753, true];

// in this example, $1 is going to be replaced with 'Eric'
const sqlQuery = 'INSERT INTO students (first_name, last_name, mobile, gender VALUES ($1, $2, $3, $4)';

client.query(sqlQuery, inputData, whenQueryDone);
```

{% endcode %}

### SQL Entity Naming and Casing

1. Database names should match the relevant code repo name and be in snake case (i.e. lowercase with underscores between words). For example, `ufo_express`.
2. Table names are pluralised snake case. For example, `ufo_sightings`.
3. Column names are singular snake case. For example, `ufo_shape`.
4. We use snake case for SQL because SQL entities are case-insensitive, and - is a special character in some SQL implementations, while \_ is not.

## Postgres and Express

When developing full stack applications we will need to interface our Postgres database with the Express Application such that we can fire off functions that query the database through API's.&#x20;

To run the code below you will need to install Express into the same npm initialised directory that you created for the previous code block. Run this command:

```
npm install express
```

Alter the current index.js to reflect the code below, changing the value of`<MY_UNIX_USERNAME>`.&#x20;

**index.js**

{% code overflow="wrap" %}

```javascript
const express = require('express');
const pg = require('pg');

// Initialise DB connection
const { Pool } = pg;
const pgConnectionConfigs = {
  user: '<MY_UNIX_USERNAME>',
  host: 'localhost',
  database: '<MY_UNIX_USERNAME>',
  port: 5432, // Postgres server always runs on this port by default
};
const pool = new Pool(pgConnectionConfigs);

const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: false }));

// Code to retireve all rows from the students table
app.get('/', (request, response) => {
  console.log('request came in');

  const whenDoneWithQuery = (error, result) => {
    if (error) {
      console.log('Error executing query', error.stack);
      response.status(503).send(result.rows);
      return;
    }
    console.log(result.rows[0].name);
    response.send(result.rows);
  };

  // Query using pg.Pool instead of pg.Client
  pool.query('SELECT * FROM students', whenDoneWithQuery);
});

// Code to insert a student into the students table
app.post('/', (request, response) => {
  console.log('request came in');
  console.log(request.body)
  
  let first_name = request.body.first_name;
  let last_name = request.body.last_name;
  let mobile = request.body.mobile;
  let gender = request.body.gender;  

  const whenDoneWithQuery = (error, result) => {
    if (error) {
      console.log('Error executing query', error.stack);
      response.status(503).send(result.rows);
      return;
    }
    console.log(result.rows);
    response.send(result.rows);
  };

  // Query using pg.Pool instead of pg.Client
  pool.query(`INSERT INTO students (first_name, last_name, mobile, gender) VALUES ('${first_name}', '${last_name}', ${mobile}, ${gender})`, whenDoneWithQuery);
});


app.listen(3004);
```

{% endcode %}

Note: There is no need to run `pool.end` like how we ran `client.end` with the `pg` `Client` class in our Node CLI apps. This is because in server applications we expect the DB connection to persist beyond individual requests.

**Command Line**

```
node index.js
```

### Exercise

Develop a put and delete handler within this Express application.

* The put request should alter an existing student stored within your tables, you may need to use request parameters here.
* The delete request should remove a student from your tables, again, consider using request parameters.
* Test your API calls using [Thunder Client](https://bootcamp.rocketacademy.co/2-full-stack/2.1-internet-101/2.1.2-http-requests-and-responses#thunder-client).


# 3.2.6: DBeaver

## Learning Objectives

1. DBeaver is a universal database management tool that interfaces with multiple database systems, including PostgreSQL.&#x20;
2. DBeaver allows developers to interface with SQL database using a GUI, using this tool you can make alterations to the database, visualise table relationships and more.
3. Understand how to install and utilise DBeaver to interface with a PostgreSQL database on your machine.

## Installation

To install DBeaver please goto this [link](https://dbeaver.io/download/) and follow the installation instructions specific to your operating system. Once you have completed the installation you will be able to interface with your PostgreSQL database, provided it is currently running on your machine. With this in mind, you will have to connect to each database currently running on PostgreSQL if you want to interface with the database.

Open the DBeaver application and you should see something similar to the image below:

<figure><img src="/files/qDjerlL9VPRXgH2NQWGx" alt=""><figcaption><p>DBeaver Interface</p></figcaption></figure>

For detailed instructions on how to use this tool please refer to this [manual](https://dbeaver.com/doc/dbeaver.pdf).&#x20;

## Interfacing with your database&#x20;

To interface with your database you will need to configure your database connection, please follow the instructions below:&#x20;

1. Click on the "Database" menu and select "New Database Connection".
2. In the "Connection Type" dropdown menu select "PostgreSQL".
3. Fill in the required credentials, these should be the same credentials you use in Sequelize to interface with your database, the credentials include:
   1. Host. Eg: "localhost"
   2. Port. Eg: "5432"
   3. Database Name. Eg: "fruit"
   4. Username. Eg: "postgres"
   5. Password. Eg: ""
4. Now you can click the "Test Connection" button to verify that the connection is successful.&#x20;
5. Once tested click "Finish" to save this connection configuration.

## Managing your database with DBeaver

Once DBeaver has been installed and you have connected to your databases you will be able to explore your database structure, all you need to do is expand the connection. This is on the left side of the application.

<figure><img src="/files/1NTut6TWbysFV0b2YUgd" alt="" width="275"><figcaption><p>Navigation DBeaver</p></figcaption></figure>

From here you can select a database and choose to look at the "Properties" or "ERD". This is on the right side of the application.

<figure><img src="/files/4OHmJsvY4JdCDUljMN8G" alt=""><figcaption><p>DBeaver Table Schema</p></figcaption></figure>

Within "Properties" you can see the table schemas and even the data currently residing in your tables.

If you click on ERD on the otherhand, an image like below will appear:

<figure><img src="/files/63ctdILHSYA8wtZmMKGB" alt=""><figcaption><p>DBeaver ERD</p></figcaption></figure>

## Data Manipulation

Using DBeaver  you are able to select individual tables such that you can manipulate the data stored within. To do this use the editor portion of the application, and tool bar at the bottom of the page. This affords developers an easier way to manage data instead of interfacing with PostgreSQL using just the CLI.&#x20;

<figure><img src="/files/OpDP1vVLhxYinFXYjpXN" alt=""><figcaption><p>Where to edit your table</p></figcaption></figure>

### Data Transfer

Another helpful feature of DBeaver is data transfer, this is crucial such that you can export and import data in various formats as well as transferring data between tables within the same or to other databases. Exporting data is rather simple but when you're trying to import data there are a few more steps. If you are interested in attempting this follow this [guide](https://dbeaver.com/docs/dbeaver/Data-transfer/).

It should be noted, at Rocket Academy we suggest utilising Sequelize Migrations and Seeders to setup the database, this means that importing data using DBeaver isn't what we suggest. It should be noted you can construct Seeder files using NodeJs's inbuilt module [fs](https://nodejs.org/api/fs.html) and [csv-reader](https://www.npmjs.com/package/csv-reader) or [csv-parser](https://www.npmjs.com/package/csv-parser). If you would like to explore this style of seed development you can use this [article](https://stackoverflow.com/questions/44912892/how-to-easily-parse-csv-file-to-use-in-node-js-sequelize-database-migration-stra) as a reference point, you may need to alter the code to suit your table structure.&#x20;


# 3.3: Sequelize

## Learning Objectives

1. ORMs allow us to query SQL databases using application languages such as JavaScript
2. Sequelize is the most popular JavaScript ORM
3. Understand basic Sequelize setup and usage
4. Models tell our apps what data they can access; Migrations tell our databases how to be structured

## Introduction

ORMs (Object-Relational Mappings) allow us to manage and query SQL databases using application languages like JavaScript without having to write SQL. This makes our applications more robust because it reduces human error from typos in SQL queries which are typically written as strings. ORMs are a layer on top of SQL, where ORMs translate application code to SQL before querying SQL DBs.

Sequelize is the most popular JavaScript ORM and we will use Sequelize in our applications during Bootcamp. The following sections follow official Sequelize tutorials. There is no need to remember all implementation details from the tutorials. Feel free to skim them, understand high-level concepts and refer back to the tutorials during implementation.

{% embed url="<https://youtu.be/XB-0A5nQS1s>" %}
Introduction to Databases&#x20;
{% endembed %}

{% embed url="<https://youtu.be/6OBhgbS5J-Q>" %}
Table Relationships
{% endembed %}

{% embed url="<https://youtu.be/dl33mcglPCI>" %}
Sequelize Migrations, Seeders and Models
{% endembed %}

{% embed url="<https://youtu.be/7Gcm2LjQBYI>" %}
Setting up Sequelize in an Express App
{% endembed %}

{% embed url="<https://youtu.be/r8U6YKuIIR4>" %}
Sequelize Migrations
{% endembed %}

Please checkout the finished code in this [repository](https://github.com/rocketacademy/m3_sequelize_repo/tree/initial_setup), ensure that you're on the `initial_setup` branch.

## Migrations

{% embed url="<https://sequelize.org/docs/v6/other-topics/migrations/>" %}
Sequelize official tutorial on Sequelize migrations
{% endembed %}

1. We will use migrations to set up our DB schema, the structure of our database, or the tables and their relationships. All companies use migrations to manage DB schema. Rocket considers migrations a core concept of Sequelize and ORMs in general.
2. Migrations at Rocket will only have "development" and "production" environments for simplicity. Tech teams in industry often have "test" environments for more robust testing between development and production.
3. We will use `model:generate` at Rocket to generate model and migration files ( This is done below)
4. You may also use  a command like this: `npx sequelize migration:generate --name products`
5. Rocket will use `.sequelizerc` to specify Sequelize file and folder paths as per the example in "The `.sequelizerc` file" section
6. We will not use concepts from "Dynamic configuration" onward during Rocket's Bootcamp

{% embed url="<https://youtu.be/yCPssb0sxds>" %}
Primary Migrations
{% endembed %}

{% embed url="<https://youtu.be/zJglYvFliiA>" %}
Secondary Migrations
{% endembed %}

{% embed url="<https://youtu.be/4Wrx_hn_RbM>" %}
Tertiary Migrations
{% endembed %}

Please checkout the finished code in this [repository](https://github.com/rocketacademy/m3_sequelize_repo/tree/migrations), ensure that you're on the `migrations` branch.

## Seeders

{% embed url="<https://sequelize.org/docs/v6/other-topics/migrations/#creating-the-first-seed>" %}
Sequelize official tutorial on Sequelize Seeders
{% endembed %}

1. We use seeder files to setup the initial data that can be used to populate our database. All companies will likely seed dummy data so that developers can collaborate and work with similar data.
2. We will use  `npx sequelize seed:generate --name products` command in order to generate our Seeder file
3. Rocket will use seed files to populate initial data in our applications

{% embed url="<https://youtu.be/U4ymjMHCya0>" %}
Primary Seeders
{% endembed %}

{% embed url="<https://youtu.be/sBYRyUEuULM>" %}
Secondary Seeders
{% endembed %}

{% embed url="<https://youtu.be/BKNk_bh6fFk>" %}
Tertiary Seeders
{% endembed %}

Please checkout the finished code in this [repository](https://github.com/rocketacademy/m3_sequelize_repo/tree/seeders), ensure that you're on the `seeders` branch.

## Running Migrations and Seeders

{% embed url="<https://youtu.be/ug3ZE7e0Abw>" %}
Migration Alteration
{% endembed %}

{% embed url="<https://youtu.be/cWwxuWO-bu8>" %}
Seeder Alteration
{% endembed %}

{% embed url="<https://youtu.be/97n2BR5doxM>" %}
Running Migrations and Seeders
{% endembed %}

Please checkout the finished code in this [repository](https://github.com/rocketacademy/m3_sequelize_repo/tree/running_migrations_seeders), ensure that you're on the `running_migrations_seeders` branch if you want to test out the migrations and seeders on your machine you will need to install the dependencies with the command `npm install` after the installation you need to setup your database connections and `.env` after this you can run the migrations, and seeders.

## Model Basics

{% embed url="<https://sequelize.org/docs/v6/core-concepts/model-basics/>" %}
Sequelize official tutorial on Sequelize models
{% endembed %}

1. A Model is an abstraction that represents a table within your database,  in Sequelize the Model is a class, the instances of this class represent the data stored.&#x20;
2. We will `Extend the Sequelize` `Model` to define models at Rocket
3. We will use default table name inference for all Sequelize examples at Rocket, which automatically assumes table names are the pluralised form of model names
4. When passing in the second object that contains sequelize, we will pass two more key value pairs :&#x20;
   1. `modelName: '<lowercase-name-of-model'>`
   2. `underscored: true`
5. We will not use `model.sync` to synchronise models with databases because that behaviour is not production-safe. We will instead use [database migrations](https://sequelize.org/docs/v6/core-concepts/model-basics/#synchronization-in-production).

{% hint style="info" %}
**Require vs Import Statements**

You may notice that Sequelize docs use `require` syntax to import modules. This is an older import syntax that Node.js still supports. Rocket recommends using `import` syntax for all code we write, and to update file extensions to `.cjs` (short for CommonJS) instead of `.js` for files that use `require` syntax. To enable `import` syntax for all `.js` files by default, Rocket has included a `"type": "module"` setting in `package.json` in all Rocket starter code.
{% endhint %}

## Model Instances

{% embed url="<https://sequelize.org/docs/v6/core-concepts/model-instances/>" %}
Sequelize official tutorial on Sequelize model instances
{% endembed %}

1. An instance of the Model class represents a row of data that is stored within the Sequelize database.
2. We will use the `create` method to create model instances at Rocket instead of `build` and `save`.
3. Rocket recommends using the suggested way to log model instances with `.toJSON()`
4. Rocket recommends using `update` to update model instances for precision instead of `set` and `save`

## Model Querying - Basics

{% embed url="<https://sequelize.org/docs/v6/core-concepts/model-querying-basics/>" %}
Sequelize official tutorial on Sequelize model instances
{% endembed %}

1. Model Querying allows developers to preform CRUD like actions to our database, we can preform actions such as create, read update and delete on the database
2. We will use `Model.create()` to insert rows into our database instead of `Model.build()` and `instance.save()`
3. We will rarely need to use syntax in "Advanced queries with functions (not just columns)" section, if ever
4. We will use `Model.bulkCreate` to seed data in our databases for Rocket exercises
5. Limits and pagination will not be necessary until we have large amounts of data that slows down our apps when retrieved all at once

## Model Querying - Finders

{% embed url="<https://sequelize.org/docs/v6/core-concepts/model-querying-finders/>" %}
Sequelize official tutorial on Sequelize model finder methods
{% endembed %}

1. If you're not updating, inserting or deleting a value from your stored data, you're probably looking to list out some specific information, or even just all the data in your table, use the Model Query Finders to do this.&#x20;
2. These are some of the most common Sequelize methods we will use in our apps
3. We can use the `Instance.findAll()` method to select data from the database to use within our application
   1. You can pass in an object with a where key this helps refine your searches, check out this [example](https://sequelize.org/docs/v6/core-concepts/model-querying-basics/#the-basics).
   2. [Operators](https://sequelize.org/docs/v6/core-concepts/model-querying-basics/#operators) can also be used for advanced queries.
   3. Order and group your data, checkout this [example](https://sequelize.org/docs/v6/core-concepts/model-querying-basics/#ordering-and-grouping).

{% embed url="<https://youtu.be/0eS0f84q_RA>" %}
Sequelize Models (1)
{% endembed %}

{% embed url="<https://youtu.be/BVZS4HIERH0>" %}
Sequelize Models (2)
{% endembed %}

Please checkout the finished code in this [repository](https://github.com/rocketacademy/m3_sequelize_repo/tree/models), ensure that you're on the `models` branch.


# 3.3.1: Sequelize One-To-Many (1-M) Relationships

## Learning Objectives

1. Sequelize provides "special" relationship methods (aka mixins) attached to models to query data with 1-1, 1-M and M-M relationships
2. Understand steps to set up Sequelize's relationship methods
3. Understand how to use Sequelize's relationship methods
4. Understand how to use migrations to add foreign keys needed for Sequelize relationships

## Introduction

Sequelize makes it easy to query for data with "special" relationship methods (aka mixins) built into Sequelize. To set up these methods we will need to tell Sequelize which models are associated with each other and how they are associated, e.g. `users` and `posts` are related via a 1-M relationship. We will also need to ensure our database tables have relevant foreign key columns using migrations if necessary. We will explore what Sequelize relationship methods look like and how to set them up in this submodule.

Recall our `Users` and `Posts` example from the SQL 1-M Relationships submodule where users have many posts, and each post belongs to a single user. In that module we demonstrated how to query posts for a given user using SQL, like the following.

```sql
SELECT * from Posts where userId=2;
```

The equivalent query in Sequelize would look like the following. Note that all Sequelize query methods return JavaScript promises because the methods query a remote database. We can choose to handle these promises with `await` or `.then` syntax.

```javascript
const posts = await Post.findAll({
  where: {
    userId: 2
  },
});
```

We will use Sequelize instead of raw SQL in our apps because writing queries in JavaScript instead of SQL strings allows VS Code to more easily catch syntax errors for us. This makes our apps more robust and less verbose.

## Sequelize Associations

Let's go through Sequelize's official introduction to associations section by section.

### Defining the Sequelize associations

{% embed url="<https://sequelize.org/docs/v6/core-concepts/assocs/>" %}
Official guide to Sequelize Associations
{% endembed %}

1. Notice the 4 types of associations Sequelize uses to specify relationships between models: `HasOne`, `BelongsTo`, `HasMany` and `BelongsToMany`. We will use `BelongsTo` and `HasMany` for 1-M relationships. `HasOne` and `BelongsTo` are used for 1-1 relationships and `BelongsToMany` is used for M-M relationships.
2. To tell Sequelize that model `A` has a 1-M relationship with model `B` and `A` is the "1" and `B` is the "M" in the relationship, we would call `A.hasMany(B);` and `B.belongsTo(A);`. Both calls are needed to include Sequelize relationship methods on both `A` and `B`. Since `B` is the "M" in the relationship, Sequelize will assume there is a foreign key `AId` (by default the related model's name (i.e. `A`) followed by `Id`) that references `A`'s primary key `id` in `B`'s model and underlying SQL table.
3. No need to worry about the options 2nd parameter, `hasOne` and `belongsToMany` methods for now
4. Note in which table Sequelize expects the foreign key to be for each association. When `A.hasMany(B)`, foreign key is in the target model `B`. When `B.belongsTo(A)`, foreign key is in the source model `B`.

### Creating the standard relationships

{% embed url="<https://sequelize.org/docs/v6/core-concepts/assocs/#creating-the-standard-relationships>" %}
Official guide to Sequelize Associations: Creating the standard relationships
{% endembed %}

1. We will focus on One-To-Many relationships in this submodule with `hasMany` and `belongsTo` associations

### One-To-Many relationships (1-M)

{% embed url="<https://sequelize.org/docs/v6/core-concepts/assocs/#one-to-many-relationships>" %}
Official guide to Sequelize Associations: One-To-Many relationships
{% endembed %}

1. Note the explanation that there is only 1 option for which table contains the foreign key in a 1-M relationship: the "M" table.
2. In our apps, we will declare Sequelize associations like `Team.hasMany(Player);` and `Player.belongsTo(Team);` in class definitions in `db/models/team.js` and `db/models/player.js`, the files in which we define our models. We will declare the associations from within each class using the `this` keyword, like `this.hasMany(models.Player)` from the `Team` class and `this.belongsTo(models.Team)` from the `Player` class. More examples in "Update models and migrations" section below.
3. We will not use `sync` as explained in Rocket's previous Sequelize submodule because it can cause unintended behaviour in production.
4. No need to worry about the Options section for now, we will stick to the defaults first

### Basics of queries involving associations

{% embed url="<https://sequelize.org/docs/v6/core-concepts/assocs/#basics-of-queries-involving-associations>" %}
Official guide to Sequelize Associations: Basics of queries involving associations
{% endembed %}

1. Sequelize uses a 1-1 relationship between `Ship` and `Captain` models here but the concepts are the same for 1-M relationships
2. Lazy loading is fetching data without using joins. Eager loading is fetching data with joins using Sequelize syntax.
3. `getShip()` is one of the "special" relationship methods we mentioned at the top of this page that allow us to query related data using Sequelize. In this case, because `Ship` and `Captain` are related with a 1-1 relationship, we can call `getShip()` on an instance of `Captain` to get that captain's ship. More on these methods in the Special methods/mixins section below.
4. Eager loading can be helpful to retrieve associated data in a single database query. We will use this in our Bigfoot SQL M-M exercise.
5. Ignore the `save()` method, we will not use it because we will use the built-in `create`, `update` and `destroy` methods that perform `save` automatically.

### Special methods/mixins added to instances

{% embed url="<https://sequelize.org/docs/v6/core-concepts/assocs/#special-methodsmixins-added-to-instances>" %}
Official guide to Sequelize Associations: Special methods/mixins added to instances
{% endembed %}

1. This section documents all "special" relationship methods we referred to at the top of this page. Note that these relationship methods will only be available on model instances when we associate relevant models with the relevant association methods, e.g. `belongsTo` and `hasMany`. For example, if I declared `A.hasMany(B)` and `B.belongsTo(A)`, I could call `a.getBs()` (where `a` is an instance of model `A`) but not `b.getAs()` (where `b` is an instance of model `B`) because each `B` belongs to only 1 `A`, not multiple.
2. All Sequelize relationship methods return JavaScript promises because they query a remote database
3. In case you're wondering, "foo" and "bar" (or just "foobar") are [common placeholder names in computer science](https://en.wikipedia.org/wiki/Foobar)
4. Note Sequelize performs pluralisation automatically and intelligently such that we can assume the relationship method names use accurate English, e.g. `getPerson` for a 1-1 relationship and `getPeople` for a 1-M relationship with a `Person` model.
5. We can ignore the special methods for `belongsToMany` associations for now. We will revisit them in the Sequelize M-M submodule.
6. Great work! This is the most important section of this submodule, and we will be using these "special" relationship methods often!

### Why associations are defined in pairs?

{% embed url="<https://sequelize.org/docs/v6/core-concepts/assocs/#why-associations-are-defined-in-pairs>" %}
Official guide to Sequelize Associations: Why associations are defined in pairs?
{% endembed %}

1. Always define relationships in pairs in Sequelize, e.g. `hasMany` and `belongsTo` for 1-M relationships! This will ensure we have the relevant built-in relationship methods when we need them.
2. Ignore the sections below this one in the Sequelize Associations page. We will not use them for now, if at all at Rocket. We will solidify our fundamentals first before learning advanced concepts.

## Update models and migrations to add foreign keys

### Introduction

The above documentation showed us how to declare Sequelize associations and use Sequelize relationship methods, but touched little on how to add foreign keys in model definitions and in our database schema using migrations. For Sequelize associations to work we will also need to update model and migration files such that our models and our database have the relevant foreign keys.

Let's again use our hypothetical `Users` and `Posts` social media example where each user has many posts. Because there is a 1-M relationship between `Users` and `Posts` respectively, there needs to be a foreign key `UserId` on the `Posts` table. Let's see how our models and migrations might look with this foreign key.

### Models

Most of `db/models/user.js` where we define our `User` model is boilerplate except for `this.hasMany(models.post)` where we declare `User`'s association with the `Post` model

{% code title="db/models/user.js" %}

```javascript
"use strict";
const { Model } = require("sequelize");
module.exports = (sequelize, DataTypes) => {
  class User extends Model {
    /**
     * Helper method for defining associations.
     * This method is not a part of Sequelize lifecycle.
     * The `models/index` file will call this method automatically.
     */
    static associate(models) {
      this.hasMany(models.post);
    }
  }
  User.init(
    {
      name: DataTypes.STRING,
    },
    {
      sequelize,
      modelName: "user",
      underscored: true,
    }
  );
  return User;
};
```

{% endcode %}

Like `User`, we also declare an association in `Post`, this time `belongsTo` instead of `hasMany`. Unlike `User`, `Post` needs a foreign key to complete their 1-M relationship, and we will give this foreign key a non-default name for clarity. We define this foreign key as `AuthorId` instead of `UserId`, because `UserId` is less precise and could cause confusion as more users are associated with posts, e.g. users that like or comment on posts.

There are 2 points to note:

1. In our association method `belongsTo` we add a 2nd options parameter `{ as: "Author" })` that instructs Sequelize to use the `Author` alias for `User`s in this relationship. This has 2 consequences:
   1. All Sequelize relationship methods that would otherwise have looked like `post.getUser()` will now look like `post.getAuthor()` instead ([official explanation](https://sequelize.org/docs/v6/core-concepts/assocs/#note-method-names))
   2. Sequelize now expects there to be a foreign key `AuthorId` on the `Post` model and `Posts` table instead of `UserId`
2. We define the foreign key `AuthorId` as a property of the `Post` model. In addition to specifying the property's data type, we also specify the model and property this foreign key references, in this case the `id` property of the `User` model.

{% code title="db/models/post.js" %}

```javascript
"use strict";
const { Model } = require("sequelize");
module.exports = (sequelize, DataTypes) => {
  class Post extends Model {
    /**
     * Helper method for defining associations.
     * This method is not a part of Sequelize lifecycle.
     * The `models/index` file will call this method automatically.
     */
    static associate(models) {
      this.belongsTo(models.user, { as: "author" });
    }
  }
  Post.init(
    {
      date: DataTypes.DATE,
      content: DataTypes.TEXT,
      AuthorId: {
        type: DataTypes.INTEGER,
        references: {
          model: "user",
          key: "id",
        },
      },
    },
    {
      sequelize,
      modelName: "post",
      underscored: true,
    }
  );
  return Post;
};
```

{% endcode %}

The above changes will allow us to use Sequelize relationships in our apps, assuming our underlying SQL database also has the relevant foreign keys. We will need to add new database migrations to add relevant foreign keys to our database schema.

### Migrations

The following database migrations assume we do not have existing tables in our database. If we do have existing tables in our database whose schemas need to be edited, we will either need to:

1. Edit existing migrations, drop existing database (`dropdb` is a convenient CLI method), create new database (`createdb` is a convenient CLI method) and re-run migrations (`npx sequelize db:migrate`)
2. Create new migrations to edit tables in existing database (`npx sequelize migration:generate`)

Rocket recommends option #1 for apps with no live user data to maximise development speed. Apps with live user data only have option #2, since we should never drop a database with live user data.

The migration to create the `users` table has no foreign key, since there is no foreign key on the `User` model.

{% code title="20220531155824-create-user.js" %}

```javascript
"use strict";
module.exports = {
  async up(queryInterface, Sequelize) {
    await queryInterface.createTable("users", {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER,
      },
      name: {
        type: Sequelize.STRING,
      },
      created_at: {
        allowNull: false,
        type: Sequelize.DATE,
      },
      updated_at: {
        allowNull: false,
        type: Sequelize.DATE,
      },
    });
  },
  async down(queryInterface, Sequelize) {
    await queryInterface.dropTable("users");
  },
};
```

{% endcode %}

The migration to create the `posts` table contains the `author_id` foreign key, declared almost identically as it was in `db/models/post.js` above. Sequelize expects the value for the `models` key in the `references` object to reference a plural table name. Documentation for declaring foreign keys in migrations [here](https://sequelize.org/api/v6/class/src/dialects/abstract/query-interface.js~queryinterface#instance-method-createTable).

{% code title="20220531155825-create-post.js" %}

```javascript
"use strict";
module.exports = {
  async up(queryInterface, Sequelize) {
    await queryInterface.createTable("posts", {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER,
      },
      date: {
        type: Sequelize.DATE,
      },
      content: {
        type: Sequelize.TEXT,
      },
      author_id: {
        type: Sequelize.INTEGER,
        references: {
          model: "users",
          key: "id",
        },
      },
      created_at: {
        allowNull: false,
        type: Sequelize.DATE,
      },
      updated_at: {
        allowNull: false,
        type: Sequelize.DATE,
      },
    });
  },
  async down(queryInterface, Sequelize) {
    await queryInterface.dropTable("posts");
  },
};
```

{% endcode %}

Once we have updated our models to include associations and foreign keys, updated our migrations to include foreign keys and run those migrations on our database, we are ready to start using Sequelize relationship methods in our apps!

{% hint style="info" %}
**New to Rocket Academy?**

If you're not enrolled in Rocket's Bootcamp and visiting this page, [check out our website](https://www.rocketacademy.co/courses/bootcamp-course) to learn more about our Bootcamp course!
{% endhint %}


# 3.3.2: Sequelize Many-To-Many (M-M) Relationships

## Learning Objectives

1. Sequelize provides relationship methods to query for data related through M-M relationships
2. Understand how to set up models and migrations to support M-M relationships with Sequelize
3. Understand how to query data related through M-M relationships with Sequelize
4. Understand how to add and query for data in junction tables for M-M relationships

## Introduction

Similar to 1-M relationships, Sequelize provides relationship methods for M-M relationships that make it easy to query related data. Using our `Person` and `Personality` example from the SQL M-M submodule where each person can have many personalities and vice versa, Sequelize allows us to call methods such as `person.getPersonalities()` and `personality.getPeople()` to retrieve related data.

The following is Sequelize's official introduction to M-M relationships with Sequelize.

{% embed url="<https://sequelize.org/docs/v6/core-concepts/assocs/#many-to-many-relationships>" %}
Official guide to Sequelize Associations: Many-To-Many relationships
{% endembed %}

1. Note the concept of the junction table is central to many to many relationships
2. In Sequelize's example their junction table is called `actor_movies`, but it could also have been called `movie_actors` if they wanted. The convention is to name the junction table with both model names concatenated, where the 1st model name is singular and the 2nd is plural. It does not matter which model is 1st and which is 2nd.
3. Note that we declare an M-M relationship between 2 models with the `belongsToMany` association method, where we specify the junction table name in a 2nd parameter with a `through` attribute
4. We will need to create the junction table `actor_movies` using a migration because we are not using Sequelize `sync`
5. There is no need to define the `actor_movies` junction model ourselves unless we plan to include non-foreign-key data in that model. However, we will always need to create the `actor_movies` table with a migration because Sequelize will not create it for us.

## Models and Migrations for M-M relationships with Sequelize

We will continue with the `People` and `Personalities` examples from the SQL M-M Relationships submodule.

### When to define new model for junction table

If the 2 tables we are associating with an M-M relationship do not need to store non-foreign-key data in their junction table, we do not need to create a standalone model for the junction table in our app. However, we will always need to use a migration to create the junction table in our database.

In this section let us assume there is no non-foreign-key data in the junction table and focus on model association methods and the migration for the junction table.

### Model association methods for M-M relationships

Given `Person` and `Personality` models, we apply the `belongsToMany` association method on each of them toward the other to set up an M-M relationship in Sequelize. Like in the `Actor` and `Movie` example in the Sequelize official docs above, we declare the through table name `person_personalities` in the `belongsToMany` method. This also means we need to create a `person_personalities` table in our database using migrations.

{% code title="db/models/person.js" %}

```javascript
"use strict";
const { Model } = require("sequelize");
module.exports = (sequelize, DataTypes) => {
  class Person extends Model {
    /**
     * Helper method for defining associations.
     * This method is not a part of Sequelize lifecycle.
     * The `models/index` file will call this method automatically.
     */
    static associate(models) {
      this.belongsToMany(models.personality, { through: "person_personalities" });
    }
  }
  Person.init(
    {
      name: DataTypes.STRING,
    },
    {
      sequelize,
      modelName: "person",
      underscored: true,
    }
  );
  return Person;
};
```

{% endcode %}

{% code title="db/models/personality.js" %}

```javascript
"use strict";
const { Model } = require("sequelize");
module.exports = (sequelize, DataTypes) => {
  class Personality extends Model {
    /**
     * Helper method for defining associations.
     * This method is not a part of Sequelize lifecycle.
     * The `models/index` file will call this method automatically.
     */
    static associate(models) {
      this.belongsToMany(models.person, { through: "person_personalities" });
    }
  }
  Personality.init(
    {
      trait: DataTypes.STRING,
    },
    {
      sequelize,
      modelName: "personality",
      underscored: true,
    }
  );
  return Personality;
};
```

{% endcode %}

### Junction table migration for M-M relationships

Now that we've set up the M-M association between `Person` and `Personality` models, let's create a migration to create the junction table `person_personalities` in our database. The following migration assumes we have past migrations that have already created `people` and `personalities` tables.

{% code title="20220531155826-create-personpersonality.js" %}

```javascript
"use strict";
module.exports = {
  async up(queryInterface, Sequelize) {
    await queryInterface.createTable("person_personalities", {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER,
      },
      person_id: {
        type: Sequelize.INTEGER,
        references: {
          model: "people",
          key: "id",
        },
      },
      personality_id: {
        type: Sequelize.INTEGER,
        references: {
          model: "personalities",
          key: "id",
        },
      },
      created_at: {
        allowNull: false,
        type: Sequelize.DATE,
      },
      updated_at: {
        allowNull: false,
        type: Sequelize.DATE,
      },
    });
  },
  async down(queryInterface, Sequelize) {
    await queryInterface.dropTable("person_personalities");
  },
};
```

{% endcode %}

Notice there are 2 foreign keys in the `person_personalities` junction table, 1 referencing the `people` table and the other referencing the `personalities` table. Even though the key in the `references` object is `model`, Sequelize expects the value to be a plural table name.&#x20;

Just like that, we've set up an M-M association in our app and are ready to start using Sequelize relationships methods on this relationship!

## Query M-M Associated Tables in Sequelize

In the Sequelize 1-M Relationships submodule we read about "special methods/mixins added to instances" and ignored the `belongsToMany` section. Let's go back and read the `belongsToMany` section to understand what relationship methods Sequelize provides to models associated with `belongsToMany`.

{% embed url="<https://sequelize.org/docs/v6/core-concepts/assocs/#foobelongstomanybar--through-baz->" %}
Official guide to Sequelize Associations: Special methods/mixins added to instances (`belongsToMany`)
{% endembed %}

1. Probably the most common relationship method we will use is `fooInstance.getBars()`, simply getting all the instances of the related table associated with the current instance. For example, `person.getPersonalities()`.
2. No need to worry about retrieving join table attributes in this section. We will explore that in the  "Handling non-foreign-key data in junction table" section below.
3. Note the large number of relationship methods we can call on model instances with a M-M relationship, including methods to count the number of related model instances, check existence of related model instances, set, add, remove, create related model instances. We will likely not need to use all of these, but good to keep in mind in case using them can simplify our code logic!
4. We can generally assume that Sequelize will get the plural form of our model names right. For example, we can assume that the Sequelize relationship method to get personalities associated with a `Person` instance will be `Person.getPersonalities()` and not something like `Person.getPersonalitys()`.

## Handling non-foreign-key data in junction table

When we wish to store and retrieve non-foreign-key data in our junction table and access that data from our apps, we will need to explicitly create a new model in our apps for the junction model. Once we've created the junction model and junction table migration we can discuss how to query the junction model in our apps.

### Models and migrations for junction tables with non-foreign-key data

#### Models

We must explicitly define the junction table model if we wish to query non-foreign-key data in the junction table. We name the model the singular of the table name, i.e. since the table name was `person_personalities`, the model is `PersonPersonality`.&#x20;

In the model is the `intensity` attribute that accompanies each person's personality trait. We also include an `id` attribute, typically omitted in models that we will include here to enable querying our junction table (more on this below). We also include the foreign keys to `People` and `Personalities` tables respectively.

Notice there are 2 `belongsTo` association methods to `Person` and `Personality` models respectively. Recall `belongsTo` associations are typically used with 1-M relationships. We included these because we want to declare 1-M associations between both `Person` and `PersonPersonality` and between `Personality` and `PersonPersonality`. We will explore why we add these 1-M relationships in the next section.

{% code title="db/models/personpersonality.js" %}

```javascript
"use strict";
const { Model } = require("sequelize");
module.exports = (sequelize, DataTypes) => {
  class PersonPersonality extends Model {
    /**
     * Helper method for defining associations.
     * This method is not a part of Sequelize lifecycle.
     * The `models/index` file will call this method automatically.
     */
    static associate(models) {
      // Define separate 1-M relationships with both Person and Personality models
      // to enable them to query junction model
      this.belongsTo(models.person);
      this.belongsTo(models.personality);
    }
  }
  PersonPersonality.init(
    {
      id: {
        type: DataTypes.INTEGER,
        primaryKey: true,
        autoIncrement: true,
        allowNull: false
      },
      PersonId: {
        type: DataTypes.INTEGER,
        references: {
          model: "people",
          key: "id",
        },
      },
      PersonalityId: {
        type: DataTypes.INTEGER,
        references: {
          model: "personalities",
          key: "id",
        },
      },
      intensity: DataTypes.INTEGER,
    },
    {
      sequelize,
      modelName: "personpersonality",
      underscored:true
    }
  );
  return PersonPersonality;
};
```

{% endcode %}

To complete the 1-M relationships between `Person` and `PersonPersonality` and `Personality` and `PersonPersonality`, we will need to add a `hasMany` association in both `Person` and `Personality` models. Below is the same code as before except with the new association.

{% code title="db/models/person.js" %}

```javascript
"use strict";
const { Model } = require("sequelize");
module.exports = (sequelize, DataTypes) => {
  class Person extends Model {
    /**
     * Helper method for defining associations.
     * This method is not a part of Sequelize lifecycle.
     * The `models/index` file will call this method automatically.
     */
    static associate(models) {
      // belongsToMany is for the M-M association to query related Personality instances
      this.belongsToMany(models.personality, { through: models.personpersonality });
      // hasMany is for the 1-M association to query junction model
      this.hasMany(models.personpersonality);
    }
  }
  Person.init(
    {
      name: DataTypes.STRING,
    },
    {
      sequelize,
      modelName: "person",
      underscored: true
    }
  );
  return Person;
};
```

{% endcode %}

{% code title="db/models/personality.js" %}

```javascript
"use strict";
const { Model } = require("sequelize");
module.exports = (sequelize, DataTypes) => {
  class Personality extends Model {
    /**
     * Helper method for defining associations.
     * This method is not a part of Sequelize lifecycle.
     * The `models/index` file will call this method automatically.
     */
    static associate(models) {
      // belongsToMany is for the M-M association to query related Person instances
      this.belongsToMany(models.person, { through: models.personpersonality });
      // hasMany is for the 1-M association to query junction model
      this.hasMany(models.personpersonality);
    }
  }
  Personality.init(
    {
      trait: DataTypes.STRING,
    },
    {
      sequelize,
      modelName: "personality",
      underscored_true
    }
  );
  return Personality;
};
```

{% endcode %}

#### Migrations

Reference the `person_personalities` migration above on this page. Add an `intensity` column to the `person_personalities` table with integer data type.

### Querying junction tables with non-foreign-key data

Sequelize has a separate, comprehensive guide to M-M relationships that includes how to manage non-foreign-key data in junction tables.

#### Defining junction model to access non-foreign-key junction table attributes

{% embed url="<https://sequelize.org/docs/v6/advanced-association-concepts/advanced-many-to-many/>" %}
Official Sequelize guide: Advanced M:N Associations
{% endembed %}

1. The content on calling `belongsToMany` association methods is the same as what we read above
2. Note: defining the junction model ourselves allows us to specify non-foreign-key junction model values when calling Sequelize M-M relationship methods such as `fooInstance.addBar()`, or in the example on this page, `user.addProfile()`.
3. No need to worry about composite unique key for now, assume `id` is still the primary key for the junction table

#### Through table versus normal tables and the "Super Many-to-Many association"

{% embed url="<https://sequelize.org/docs/v6/advanced-association-concepts/advanced-many-to-many/#through-tables-versus-normal-tables-and-the-super-many-to-many-association>" %}
Official Sequelize guide: Advanced M:N Associations - Super Many-to-Many association
{% endembed %}

1. Having an `id` primary key on `PersonPersonalities` model is necessary for the "Super Many-to-Many relationship" that allows both `Person` and `Personality` instances to query both the junction table and the table associated via the M-M relationship. I.e., to allow `Person` to query both related `PersonPersonality` and `Personality` instances, vice versa for `Personality`.
2. Notice that the tables in the database look the same regardless of whether we declare 2 1-M relationships between `person` and `person_personality` and `personality` and `person_personality`, or 1 M-M relationship between `person` and `personality`.
3. The "Super Many-to-Many relationship" requires us to declare 1-M relationships between the 2 M-M tables and the junction table, and an M-M relationship between the 2 M-M tables. In our `person` and `personality` example, this means declaring 1-M relationships between `person` and `person_personality` and between `personality` and `person_personality`, and an M-M relationship between `person` and `personality`.
4. We can ignore everything below "Aliases and custom key names" in the Sequelize M:N Associations guide for now. Those concepts are more advanced and we can come back to them as reference if we need them.

#### Querying the junction model

With the "super M-M relationship" we can query our junction model in multiple ways. The cleanest way is to query using M-M relationship methods with the `joinTableAttributes` option.

```javascript
person.getPersonalities({ joinTableAttributes: ['intensity'] });
```

Alternatively we can use 1-M relationship methods to access the junction table, but that may require more acrobatics with `Person` and `Personality` IDs.

## Additional Resources

1. [React Select](https://react-select.com/home) is a React component library that provides an elegant UI for collecting 1-M and M-M relationship data.


# 3.3.3: Advanced Sequelize Concepts

## Learning Objectives

1. Sequelize model aliases and custom foreign keys can make our app logic clearer, especially when our schemas involve models with multiple associations with any other model
2. Sequelize eager loading can make our database querying more efficient by retrieving all data we need from multiple tables in a single query instead of multiple
3. Sequelize validations and constraints can make our applications more robust by allowing us to prompt our users when input data is invalid, and preventing us from saving invalid data to our databases

## Introduction

The Sequelize concepts in this module will not be necessary for many applications, but they are commonly used in industry, especially for more complex apps with many features, more related data that is queried often, and greater requirements for data integrity.

These Sequelize concepts do not appear often in coding interviews, although related concepts have come up in interviews, such as how to perform joins in SQL queries and how to ensure data integrity in a database.

## Association Aliases & Custom Foreign Keys

Sequelize allows us to define aliases for models in associations. This is especially helpful in situations where a model has multiple associations with another model, for example in our Carousell app where the `Listing` model has multiple associations with the `User` model, 1 for buyer and 1 for seller.

The following official Sequelize guide shares an example of a sports game model associated twice with a team model, once for home team and once for away team. Rocket implemented the listing, buyer and seller associations similarly in our Carousell reference solution.

{% embed url="<https://sequelize.org/docs/v6/core-concepts/assocs/#multiple-associations-involving-the-same-models>" %}
Official guide to Sequelize Associations: Multiple associations involving the same models
{% endembed %}

1. Notice the example specifies both aliases and custom foreign keys. In our experience, when using aliases it's better practice to specify a custom foreign key to have clearer control over Sequelize.

The following section in the guide shares all the different ways to define and uses Sequelize aliases and foreign keys.

{% embed url="<https://sequelize.org/docs/v6/core-concepts/assocs/#association-aliases--custom-foreign-keys>" %}
Official guide to Sequelize Associations: Association Aliases & Custom Foreign Keys
{% endembed %}

1. There is no good reason for now to specify a custom foreign key unless we are using Sequelize aliases
2. Aliases are primarily useful for Sequelize relationship methods, because we will be able to use the relationship methods with alias names to query related data, which should clarify our app logic

## Eager Loading

Eager loading is an optimisation and optional at Rocket Academy. We will always be able to retrieve the data we need with multiple, simpler queries. If you are keen to optimise the SQL data query times in your app, read on.

The following official Sequelize tutorial on Eager Loading demonstrates the syntax for loading multiple associated tables in a single query.

{% embed url="<https://sequelize.org/docs/v6/advanced-association-concepts/eager-loading/>" %}
Official Sequelize tutorial: Eager Loading
{% endembed %}

1. Note the `include` syntax used to fetch associated model data with eager loading
2. Note the eager-loaded associated model may be an object or array of objects depending on whether the association is singular or plural
3. After "Fetching an Aliased association" section, the other sections in the "Basic example" are nice to know and not necessary for now
4. Retrieving junction table attributes with eager loading for M-M relationships can be helpful when we have non-FK data in our junction tables, such as `intensity` in our `person` and `personalities` example from the Sequelize M-M Relationships submodule
5. Including all nested associated models is discouraged for performance reasons, less we truly need all that data at once
6. Everything from "including soft deleted records" to "Using `findAndCountAll` with includes" is optional, we will not need to read it in detail until we need it

## Validations & Constraints

Sequelize validations and constraints make our applications more robust by preventing users from inputting invalid data, and preventing our application logic from saving invalid data to our database.

Sequelize validations and constraints are not necessary for our relatively simple applications at Rocket, but will be more important when we work at companies that require high levels of data integrity, especially those that work with financial or healthcare data.

Sequelize performs validations defined in models at the application level in JavaScript, and instructs SQL (Postgres in our case) to perform constraints defined in migrations at the database level. Validations typically check for requirements that can be verified without database queries, such as capitalisation, valid email, is numeric. Constraints typically check for requirements that require database queries, such as whether a value is unique in a given column.

When we use validations and constraints in our code, we can surround our Sequelize model methods with try-catch blocks to catch errors when validations or constraints fail. This allows us to gracefully let our users know what happened and how to fix it.

The following official Sequelize tutorial demonstrates the syntax of defining Sequelize validations and constraints.

{% embed url="<https://sequelize.org/docs/v6/core-concepts/validations-and-constraints/>" %}
Official Sequelize tutorial: Validations & Constraints
{% endembed %}

1. There are [many validations](https://sequelize.org/docs/v6/core-concepts/validations-and-constraints/#per-attribute-validations) we can apply in Sequelize
2. We can define constraints in migrations using the same validations syntax
3. Validations are preformed in the JavaScript environment while Constrains are considered at the SQL level.&#x20;
4. Apply validations and constraints to models as well as migration files for the best result.

{% hint style="info" %}
**New to Rocket Academy?**

If you're not enrolled in Rocket's Bootcamp and visiting this page, [check out our website](https://www.rocketacademy.co/courses/bootcamp-course) to learn more about our Bootcamp course!
{% endhint %}


# 3.3.4 Database Design

A database is a representation of all of the data stored that helps facilitate your users functionalities.  This means that your database architecture should be based off your features. Consider how your application is helping your users and what they will be doing on your application. If you are completely aware of the core features and user flow of the application you will be able to make informed decisions when designing and developing your database.

### **Defining functionalities - user stories**

Say we were developing an E-commerce application where we are selling fruit. Here are some example user stories, can you think of more?<br>

Users will need to login to order and purchase fruit

Users will need to be able to track their transactions

Users will need to be able to search for fruit within our database by name

Users will need to see the current stock of items

Users can send their orders to various addresses

Users who refresh the page, or continue an order on another machine, will not lose their cart

This user stories act as a guide when developing our database. Provided we begin to follow some of the conventions for developing a relational database. So before we begin to create our database schema we should delve into some relational database rules.&#x20;

### Basic rules

Here is an example of a poorly optimised database, we apply some rules and alter this so that it is possible to create a relational database with this information.&#x20;

<figure><img src="/files/o48U4mnbxffm26qAsHv3" alt=""><figcaption><p>Poorly Designed database</p></figcaption></figure>

> Each table cell should contain a single value and every record needs to be unique

As you can see from the table above there is an issue with the column fruit\_brought, there are  multiple items listed per cell, some repeating multiple times, we will need to alter our database to represent the data more efficiently for querying.&#x20;

Example of the database with single values in each cell

<figure><img src="/files/X2lpj5WiDRGlv9W8LGGa" alt=""><figcaption><p>Getting better but not there yet<br></p></figcaption></figure>

### **Composite Keys - Do not use them**

What is a composite key?

> A composite key in SQL can be defined as **a combination of multiple columns**, and these columns are used to identify all the rows that are involved uniquely.

Here is an example of a table that uses composite keys

<figure><img src="/files/9uPOx013KWPOQ0Z9ayf2" alt=""><figcaption><p>Example of Composite keys</p></figcaption></figure>

Currently we are using composite keys to identify rows of data in the table above, full\_name could be repeated, so we would actually reference the name and email to identify the user.&#x20;

### **Importance of a Primary Key**

A primary key is:

> A primary key is **the column or columns that contain values that uniquely identify each row in a table**.

Currently we are using Composite keys to reference data, however, we should develop tables that contain primary keys to help identify and reference rows within our table. Here are some rules regarding Primary keys.

> Primary keys cannot be Null
>
> Primary keys must be unique in value (per table)&#x20;
>
> Primary keys values should rarely be changed
>
> Primary keys must be given a value when data is inserted

When using primary keys make sure that:

> Primary Keys do not functionally depend on any subset of candidate key relation

Here is an example of the of the original table using primary keys to identify the information

<figure><img src="/files/lRSir4lKKjhzXqNMXewg" alt=""><figcaption><p>Adding Primary key to Users table, and creating a Fruit table with user references</p></figcaption></figure>

### **Foreign Key**

Foreign Keys references the Primary Key of another table to reference that information set.

> A foreign key needs to have a different name from its primary key.
>
> It ensures rows in one table have corresponding rows in another.
>
> Unlike the Primary key, they do not need to be unique on a table, often they aren't.
>
> Foreign keys unlike Primary Keys can be null when you are setting the information within your database.&#x20;

Below is a representation of our table constructed with Primary and Foreign keys.

<figure><img src="/files/erD5gujoX9iFyB7PVEsh" alt=""><figcaption><p>Using a Foreign Key</p></figcaption></figure>

\
**Why do we need Primary and Foreign keys?**

<figure><img src="/files/GmQ3bQfX644aj6ogwSNI" alt=""><figcaption><p>Reasons to implement your relational database with Pk and Fk</p></figcaption></figure>

Primary and Foreign keys help us to define the relationships between our table, in this case, a 1-many relationship, a user can have multiple fruit. Without this relationship defined data integrity could not be handed by SQL.&#x20;

### Fruit E-Commerce Example

Lets continue with our E-commerce fruit store example. We will need a few tables that define our relational database schema. As stated before the functionalities of the application will dictate the information that is stored within our database. So lets start with the first functionality, <br>

**Users will need to login.**

If users need to login at some point in our application we are going to need to store their credentials within our database to validate that they are users within our application, this means we will need a table to store identifying information for our users.

<br>

**Users who are logged in can order fruit**

If logged in users can order fruit from our store we will need ensure that they are presented with an array of items that they can buy, this means we will need to create and populate a fruits table that represents all of the items we can sell.&#x20;

<br>

**Users will need to be able to search for fruit within our database by name**

As stated above we are going to create a fruit table which will contain relevant information. The information that is retrieved from the database can be displayed and shown on the browser. This particular issue is more about implementation rather than database setup. There are two approaches to implementing this user story:

1. Click on a button to search for a particular fruit by name, this could call an API request that looks for a single fruit returning that data to be rendered on the screen.&#x20;
2. Call an API that retrieves all of the fruit from the backend, and then using a state and filter function on the frontend, process the given fruit and only show one.&#x20;

**Users will need to see the current stock of items**

As stated above, we are going to create a fruit table to store information regarding our fruits, if we want users to see the current stock then we just need to store the information in our Fruits table and display it when showcasing the  fruits within our store.<br>

**Users will need to be able to track their transactions**

Considering users will want to order fruit and track their previous orders we will need to develop two tables that are related.

1. An orders table to store the total and user\_id
2. An ordered\_fruit table, a junction table, to store all of the fruits within a particular order.

Here we have a one to many relationship, one order can have many ordered fruit.&#x20;

\
**Users can send their orders to various addresses**

As user will be able to send their orders to various addresses we will need to store multiple user addresses, this means we will need to create a users\_addresses table that contains each address that the user could send their fruit order to.

<br>

**Users who refresh the page, or continue an order on another machine, will not lose their cart**

This user story means that we will need to create a table that tracks fruit items and quantities of items in their cart, every time they add, edit or remove and item we will need to update this table. When the order is placed, you would remove all fruits in current\_cart table and update the ordered\_fruit, orders and fruit table. <br>

This would be the resulting database:

<figure><img src="/files/bFITxBVAcJENcApCqOfZ" alt=""><figcaption><p>Example Fruit_Store Database</p></figcaption></figure>

Now that you have designed your database you can begin to develop the Sequelize migration and seed files that you can run to create the database on your server as well as populate it with data. When developing a database we split our tables into three main migration files.

* Primary tables, tables that do not rely on any other data.
* Secondary tables, a table that contains one foreign key, normally a one to many relationship.
* Tertiary tables which represent our join tables, these tables will often contain two or more foreign keys.&#x20;

Once you run your migration and seed files developers can begin work on the actual server with models, controllers and routers, sharing a common dataset.&#x20;

## Extra Rules of databases

Another commonly accepted rule of databases is that:

> Data has no transitive functional dependencies

A transitive functional dependency is when changing non-key column (normal column), might cause any of the other non-key columns to change.

<figure><img src="/files/miIiOtZsO6ecFh0aYQCE" alt=""><figcaption><p>Transitive Dependency</p></figcaption></figure>

If a full name changes this might alter a salutation, and therefore we shouldn’t have this relationship within our schema. We will need to break the Salutation into another table that we can reference.&#x20;

<figure><img src="/files/37AQl4XxOPIbvcutqsnA" alt=""><figcaption><p>Redesigned Initial Database</p></figcaption></figure>

There are further rules, but lets not deal with those at this moment, if you want to read more, please look into this link.

[What is Normalization in DBMS (SQL)? 1NF, 2NF, 3NF Example](https://www.guru99.com/database-normalization.html)


# 3.4: Authentication

## Learning Objectives

1. Understand the flow of typical authentication processes and how they use JWTs and cookies
2. Understand how to implement secure authentication with Auth0

## Introduction

Authentication is both simple and complex. The high-level concept of authenticating a user, then saving that user's authentic "badge" in their browser for subsequent requests is simple. But the lower-level concepts of how to authenticate and how to save that badge in the browser can be complex.

At Rocket Academy we will focus on the higher-level concepts of authentication, and let students dig deeper into the lower-level concepts themselves if time permits and students are interested. We will use [Auth0](https://auth0.com/) to implement authentication in our API servers, the industry standard for plug-and-play authentication libraries, comparable to Firebase Auth but with friendlier docs.

{% embed url="<https://youtu.be/cBLCVjyuUsY>" %}
What is auth0?
{% endembed %}

{% embed url="<https://youtu.be/KhlqoxD3YBM>" %}
auth0 Online
{% endembed %}

{% embed url="<https://youtu.be/6btuQC4dSsE>" %}
auth0 Documentation
{% endembed %}

## Basic Authentication Flow

At a fundamental level, all authentication involves 3 steps.

1. User enters auth info such as username and password
2. Backend verifies auth info via cryptographic algorithm, typically involving [hashing](https://en.wikipedia.org/wiki/Cryptographic_hash_function) and [salting](https://en.wikipedia.org/wiki/Salt_\(cryptography\)). Verification involves comparing the hashed version of the provided password with the hashed password stored in the database. We never store plain-text passwords for security reasons.
3. If auth info verified, backend sends user's browser a [cookie](https://en.wikipedia.org/wiki/HTTP_cookie) that contains proof of authentication, typically either a [JSON web token](https://en.wikipedia.org/wiki/JSON_Web_Token) (JWT) or a [session ID](https://en.wikipedia.org/wiki/Session_ID) that cannot be forged. Browsers store cookies and send them to relevant websites, thereby proving authentication.

Authentication can be challenging because it involves many moving parts. Our server application must store auth info such as passwords and secret keys securely. Our cryptographic algorithm and proof of authentication must be industry-standard. Any bugs in logic or implementation can result in costly hacks.

This is why Rocket recommends we use a plug-and-play, industry-standard auth solution such as Auth0, and only write our own lower-level authentication logic when there is a strong business need and we have experts to test the robustness of our implementation.

## Implementing Authentication with Auth0

Luckily for us, companies such as Auth0 and Firebase have developed plug-and-play auth solutions that are both secure and easy to use. We will use Auth0 for backend authentication because Auth0 has clearer documentation for this use case.

### Setup Auth0 account and initial app

1. Create Auth0 account if we haven't already
   1. Yes, we will be the one coding
   2. No, we do not need advanced settings
2. Create Application
   1. Choose Single Page Web Application
   2. Choose React

### Review how to authenticate in React app

We should then be directed to a quickstart page like the following, populated with our app's specific domains and IDs. No need to implement anything for now, but read through to understand the high-level process.

{% embed url="<https://auth0.com/docs/quickstart/spa/react/01-login>" %}
Official Auth0 setup guide for React apps
{% endembed %}

1. Note application domain and client ID in Application Settings in the Auth0 dashboard. We will need to include these in our app to communicate with Auth0.
2. Configure callback and logout URLs to allow redirects back to our apps after logging in or out with Auth0
3. Configure allowed web origins to allow auth tokens (JWTs that serve as proof of authentication) to automatically refresh periodically after users have logged in to prevent auto-logout when auth tokens expire
4. Surround `App` component with `Auth0Provider` component to enable Auth0 in our apps. Note `Auth0Provider` uses React context underneath.
5. Add login to app with `loginWithRedirect` function from `useAuth0` React hook. Login is as simple as calling the function, letting users login in Auth0's interface, then redirecting back to our app.
6. Ditto with the `logout` function also from the `useAuth0` React hook. `returnTo: window.location.origin` tells Auth0 to redirect to the root URL of the current browser window after logging out.
7. Retrieve logged-in user profile information through the `user` property of the `useAuth0` hook. `user` contains properties such as `picture`, `name` and `email`.

That's all there is to logging in and out with Auth0 in our frontend! Let's now learn how to send that auth info to our backends for our users to access our backends securely.

### Review how to pass authentication info to API from React app

Now that we've enabled login in our React apps, we need to learn how to pass an access token from Auth0 to our backends to verify authentication.

{% embed url="<https://auth0.com/docs/quickstart/spa/react/02-calling-an-api>" %}
Official Auth0 API-calling guide for React apps&#x20;
{% endembed %}

1. Our frontends authenticate with our backends via an access token that we retrieve from Auth0 on our frontends, send to our backends in a request, and verify using an Auth0 library on our backends.
2. To retrieve this access token on our frontends, we need to pass additional `audience` and `scope` props to the `Auth0Provider` component.
   1. `audience` is an identifier for our API server that we set in Auth0. This is typically the URL of our API server.
   2. `scope` is a property we define in Auth0 that allows us to only allow access to specific backend routes from specific frontend apps. In our case we will keep scope simple and allow access to all protected routes from our frontend.
3. Retrieve access token with `getAccessTokenSilently` method from `useAuth0` React hook
4. Use `getAccessTokenSilently` to retrieve access token just before we send an API request via Axios. In Auth0's example they use Fetch to send requests, but the concept is the same.
   1. Pass `audience` and `scope` again to `getAccessTokenSilently` to get a token for the correct domain and scope
   2. We need to include the access token in an "Authorization" request header with the format shown in this guide. Our API server will need the header in this format to process the access token.

Voila! We are now ready to set up authorisation in our backends for protected routes!

#### (Legacy React CRA)&#x20;

{% embed url="<https://youtu.be/CQpz8rHwONk>" %}
auth0 Frontend Setup
{% endembed %}

{% embed url="<https://youtu.be/AwM2cA5kZpQ>" %}
Access Token & Post Request
{% endembed %}

### <mark style="color:red;">Auth0 Update:</mark>

When defining the Auth0Provider, there has been a slight alteration!\
Please pass in the property authorizationParams to include the redirectUri, audience and scope. Similar to the code below:

```javascript
<Auth0Provider
    domain='<Your-auth-domain>'
    clientId='<Your-client-id>'
    authorizationParams = {{ 
      redirectUri: window.location.origin,
      audience: "<Your-app-API->",
      scope: "read:current_user update:current_user_metadata openid profile email",
    }} 
>
// Make sure you alter the credentials passed above 
```

### Authorise access to protected routes in Express backend

We will implement authentication in our backend first because there are certain credentials to set up for our API server that we will need to use in our frontends later.

Some routes in our backend will be protected, for example routes to access user data or manipulate data. Based on the logged-in user, backends can decide what data to expose to that user and record changes by that user.

{% embed url="<https://auth0.com/docs/quickstart/backend/nodejs/01-authorization>" %}
Official Auth0 route-authorisation guide for Express apps
{% endembed %}

1. Create an API in the Auth0 dashboard and give it an identifier, typically a URL that identifies our API. We will use this API identifier as an `audience` in our frontends when retrieving an access token to communicate with our backends
2. There is no need to understand RS256 and what a private/public keypair is at the moment, other than knowing they are industry-standard security mechanisms.
3. We can ignore scope for now because our apps will be simple and all users should be able to access all features
4. Install Auth0's `express-oauth2-jwt-bearer` middleware to verify authentication on our routes
5. Initialise the middleware in the root `index.js` file of our Express app with our API's identifier as `audience` and the `issuerBaseURL` provided by Auth0 (login to Auth0 while viewing this guide to see it)
6. Insert `checkJwt` middleware in routes that require authentication, and add `checkScopes` middleware in routes that also require specific scopes.

Great job! We now have authentication and secure access to our APIs!

{% embed url="<https://youtu.be/s1d298jM61k>" %}
auth0 Backend Implementation & Testing
{% endembed %}

### Roundup

Hopefully this gave us a clear high-level overview of what steps we need to implement Auth0 authentication in our frontends, how to send auth info in requests and protect our backends using Auth0 authorisation. We will get more hands-on practice with Auth0 in the upcoming hands-on auth exercise.

Please checkout the finished frontend code below. Note that you will need to setup a application on Auth0 that you integrate with the application.&#x20;

Frontend code is in this [repository](https://github.com/rocketacademy/3.2_react_repo/tree/auth), ensure that you're on the `auth` branch if you want to test the code on your machine you will need to install the dependencies with the command `npm install` after the installation you can run the application with `npm run dev`. To view the rendered page open a browser and navigate to <http://localhost:5173> Note, you will need to create your own .env and create your own Auth0 application online with the appropriate setup. To test it with a backend please checkout this [repository](https://github.com/rocketacademy/m3_sequelize_repo/tree/auth), ensure that you're on the `auth` branch if you want to test the code on your machine you will need to install the dependencies with the command `npm install` after the installation, then implement you `.env` . If you've not setup the database previously, run your migrations and seeders and once this is completed you can run the application with `node index.js`.&#x20;


# 3.4.1: JWT App

## Learning Objectives

1. Comprehend why developers may want to implement their own version of authentication as opposed to using auth0 or other third party systems.&#x20;
2. Understand the implementation of JWT within a React and ExpressJs Application context.

## Introduction

When developing your own authentication system there are a few approaches that one could take. JSON Web Token or JWT is one such approach. To authenticate a user a clients application must send a JWT in the authorisation headers of the HTTP request to the Applications backend server. The backend Application's API will validate the request and token using middleware functions. JWT's allow developers to define a compact and self-contained way to securely transmit information between Frontend and Backend of the application. We use JWT tokens to authorise users within our application, when the user signs up and logs in they will be granted a JWT token which is used within the application to verify the user within the application. When a user is signed out, the token can be invalidated to ensure the security of application.&#x20;

Look into the plethora of [JWT implementations here](https://jwt.io/).&#x20;

### Auth0 or Custom implementation?

Leveraging a tool like Auth0 has many benefits first and forth most is Customisation as well as control, when building your own system you have full control over the features that are implemented. This level of customisation allows developers to build unique features like integration with an existing user database, granular access control or specific security implementations. When you have existing infrastructure such as a user database creating your own system means that you can easily integrate with them. An additional benefit of creating your own authentication system is that you have direct control over the security measures and protocols that are put into place. This gives you complete control over user data and privacy. That being said using a third-party authentication service like Auth0 does offer several advantages, you will reduce your development time, there are pre-built integrations offered by Auth0 and it contains robust security features. At the end of the day the decision to leverage a third-party authentication system or build your own depends on the projects requirements, how long the development cycle is and how much customisation and control you need.&#x20;

### Backend Implementation

When implementing JWT Authentication on an ExpressJs backend it is important to leverage certain tools such as [bcrypt](https://www.npmjs.com/package/bcrypt), to help you hash user passwords,  [jsonwebtoken](https://www.npmjs.com/package/jsonwebtoken), which provides the means to generate, verify and validate JWTs. When used in conjunction with a database system one could develop their own version of JWT authentication and have complete control over the backend authenticating and authorisation logic.&#x20;

The ExpressJS backend application will need to handle HTTP requests such that users can sign-in, sign-up and sign-out of the application, additional requests could include forgotten passwords and even alter emails. In addition to this, we should set up token expiration and refresh mechanisms to prevent unauthorised access as well as enhance security.

Note that the backend system is connected to your Frontend Application, this is done through HTTP requests that are shared between the communicating applications.&#x20;

Here is an example of how you can sign a JWT within your backend, this token must be sent to the Frontend in order for user verification. Note that this example uses a .env to store its secrets, as we are using ExpressJS we prefix the environmental variables with `process.env`.

{% code title="Token Generation" %}

```javascript
const jwt = require("jsonwebtoken");

const newAuthToken = (payload, refreshToken = false) => {
  const secretKey = refreshToken
    ? process.env.REFRESH_JWT_SECRET
    : process.env.JWT_SECRET;

  const expiresIn = refreshToken
    ? process.env.REFRESH_JWT_EXPIRES_IN
    : process.env.JWT_EXPIRES_IN;

  return jwt.sign(payload, secretKey, { expiresIn });
};

module.exports = newAuthToken;
```

{% endcode %}

Here is an example of a JWT middleware for an ExpressJs backend, it can be imported and used within the middleware chain to verify a users JWT token within their request. This is a vital implementation to ensure that only logged in users can alter and interact with the database. Notice that in the example above we are signing the JWT, while in the code below we are verifying it using methods from the `jsonwebtoken` package we just use the package for generating and verification of JWT's, not storage of our user data/ JWT information.&#x20;

{% code title="Auth Middleware" %}

```javascript
const jwt = require("jsonwebtoken");

const jwtAuth = (req, res, next) => {
  try {
    const accessToken = req.headers.authorization.split(" ")[1];
    
    if (!accessToken) {
      return res.status(401).json({
        error: true,
        msg: "Error: missing or invalid access token.",
      });
    }

    const user = jwt.verify(accessToken, process.env.JWT_SECRET);
    req.user = user;
    next();
  } catch (error) {
    return res.status(403).json({
      error: true,
      msg: "Error: unauthorised access, invalid token.",
    });
  }
};

module.exports = jwtAuth;
```

{% endcode %}

When signing up a user developers need to perform a number of tasks. First storing the user information within the database, provided that user doesn't exist, then leverage the `jsonwebtoken` package to create tokens that can be associated into the database with the current user. Then finally sending the user and token back as the response to this HTTP request. Notice how there are error handlers set up that respond or are triggerred by different issues.&#x20;

{% code title="Example Signup Func" %}

```javascript
signUp = async (req, res) => {
  const { firstName, lastName, email, password, profilePicture } = req.body;

  if (!firstName || !lastName || !email || !password || !profilePicture) {
    return res.status(400).json({
      error: true,
      msg: "Error: Please fill in all required fields and try again.",
    });
  }

  try {
    // check if user exists
    const existingUser = await this.model.findOne({
      where: { email: email },
    });

    if (existingUser) {
      return res.status(400).json({
        error: true,
        msg: "Error: An account with this email address already exists.",
      });
    }

    // step 1: hash password
    const hashPassword = await bcrypt.hash(password, saltRounds);

    // step 2: create new user
    const newUser = await this.model.create({
      firstName: firstName,
      lastName: lastName,
      email: email,
      password: hashPassword,
      profilePicture: profilePicture,
    });

    // step 3: create a payload for jwt
    const payload = {
      id: newUser.id,
      email: newUser.email,
    };

    // step 4: create tokens
    const accessToken = generateAuthToken(payload);
    const refreshToken = generateAuthToken(payload, true);
    const verificationToken = generateEmailToken();
    // step 5: update user info to include refresh token
    await this.model.update(
      {
        refreshToken: refreshToken,
        verificationToken: verificationToken,
      },
      { where: { id: newUser.id } }
    );

    const user = await this.model.findByPk(newUser.id);

    return res.status(200).json({
      success: true,
      data: { user, accessToken },
      msg: "Success: Your account has been created successfully.",
    });
  } catch (error) {
    return res.status(400).json({
      error: true,
      msg: "Error: Oops! We stumbled upon an issue while setting up your account. Please refresh the page and try again.",
    });
  }
};

```

{% endcode %}

### Frontend Implementation

To implement JWT Authentication within a React Frontend context it is necessary to integrate packages such as [axios](https://www.npmjs.com/package/axios) into your application to make the HTTP requests to faciliate user sign-in, sign-up and sign-out. Moreover its vital to create the forms to capture user authentication data such as user emails and passwords. After this is completed, we need to consider where we could store our token, it might be possible within a secure cookie or even browser localstorage.&#x20;

Upon successful login, if users want to access JWT pages then the Frontend application will need to verify that the current user has a signed and valid JWT, if the token is present then the user will gain access to the Frontend components protected by authenticating logic. If users are making requests to alter information in the ExpressJs backend then the users requests must include the JWT token for the Backend API to validate, if the token is authenticated successfully then the user will gain access to protected routes and alterations could be made. Otherwise an error message might be the response resulting in an error handler being fired off in the frontend. &#x20;

The code below is an example of how we might send the signup request from a React Frontend that is powered by Vitejs, notice how are are importing the environmental variables using `import.meta.env.VITE_SOME_` prefix.&#x20;

```javascript
const sendSignupInformation = async () => {
  ...
  const response = await axios.post(`${import.meta.env.VITE_SOME_DB_API}/auth/signup`,
        {
            firstName: firstName,
            lastName: lastName,
            email: email,
            password: password,
            profilePicture: url,
        }
    );
   ...
  }
```

Once the the React Application receives a successful response it is possible to store the received access token in a secure cookie or the browsers local storage. Use this access token to validate that a user has been logged in and setup the required statful logic to denote that a user has logged in a boolean state can suffice. To setup protected components on the Frontend using React Router follow the [Private Routing section](https://bc.rocketacademy.co/2-full-stack/2.2-advanced-react/2.2.2-react-router#private-routing).&#x20;

After a user has logged in, every subsequent request that is made to a protected backend route needs to contain their most recent access token to validate that they are actually logged in. In this example the developers store the access token into local storage.

{% code title="Update Profile Request" %}

```jsx
const handleUpdateProfile = async (inputValue) => {
    // Get the users access token from local storage
    const accessToken = localStorage.getItem("accessToken");
    try {
    // Generate an axios request to the backend
      const response = await axios.post(
        `${import.meta.env.VITE_SOME_DB_API}/user/profile`,
        {
          profilePicture: inputValue.url,
          firstName: inputValue.firstName,
          lastName: inputeValue.lastName
        },
        // place the access token within the Authorization header, as a Bearer token
        {
          headers: {
            Authorization: `Bearer ${accessToken}`,
          },
        }
      );
      ... // Reset form logic
    } catch (error) {
      //Notify the user if there is an error using a toast message
      toast.error(`${error.response.data.msg}`);
    }
  };
```

{% endcode %}

#### Additional features for consideration&#x20;

There are various additional features that could be implemented when setting up a custom version of authentication. One of the most important features that can be implemented on-top of basic authentication is an email verification system. If you are interested in setting up a password recovery system or invitation emails you could consider using [nodemailer](https://nodemailer.com/),  to power your Express application to send emails to your users. The email verification system can power your application to support forgotten passwords for your users, that respects your authentication flow and is all controlled by your backend.


# 3.5: Application Deployment

If you have time, deploy your Bigfoot project to learn full-stack app deployment prior to Project 3. We will need to deploy the backend (Express && Sequelize) and frontend (React App) onto separate servers.

## Backend

To test out and deploy our applications, you can deploy your own exercises or you can deploy this [repo's code](https://github.com/rocketacademy/bigfoot-sql-backend-bootcamp/tree/deployment_example). Clone the application pull the correct branch, deployment\_example.&#x20;

cd inside the cloned directory and run the command below:

`git fetch origin deployment_example`

`git checkout deployment_example`

### Context

We will be using [Fly.io ](https://fly.io/)to host the backend of our application, Fly.io is similar to one of the most popular application hosting services, [Heroku](https://www.heroku.com/). We are unable to user Github Pages or Firebase Hosting to deploy our backend server as those tools only support static sites, i.e. applications that do not have a database. You are able to easily sign up for Fly.io, it offers easy deployment that can be achieved through the CLI.&#x20;

<mark style="color:red;">Note: You made be asked for credit card credentials when deploying on fly.io, don't worry, sign up for the free tier service and you will not be charged. If you deploy multiple projects you may incur costs.</mark>&#x20;

### Instructions

Create a new account on Fly.io and follow the [official Node.js deployment guide](https://fly.io/docs/languages-and-frameworks/node/) to set up and deploy our backend app to Fly.io. Refer to the instructions below while creating setting up your deployed application.

{% embed url="<https://fly.io/docs/languages-and-frameworks/node/>" %}
Official Fly Node.js deployment guide
{% endembed %}

* You will need to complete the prerequisites listed within the Fly guide. If you haven't already, create a free Fly account. Install the Fly CLI by following [installation instructions](https://fly.io/docs/hands-on/install-flyctl/).&#x20;
* Make sure you are [logged in](https://fly.io/docs/getting-started/log-in-to-fly/), on the Fly CLI.
* Change directory to the root level of your backend project.&#x20;
* Run the command `flyctl launch`
* Add an Application name: i.e. `bigfootsqlrocket`
* Choose location: i.e. `Singapore`
* Setup Postgresql database now? Type: `'y'`.&#x20;
* Choose (use arrow keys): **Development - Single node, 1x shared CPU, 256MB RAM, 1GB disk (press enter)**
* Scale single node pg to zero after one hour? (y/N) Type: `'N'`.
* Fly will link the an empty PostgreSQL Database straight to your deployed backend. Save the credential details they provide for you somewhere, you will not be able to access this information again. <mark style="color:red;">These credentials are vital if your backend needs to interface with your database.</mark>

<figure><img src="/files/LSrmoYPVmJaTtwPvvuRj" alt=""><figcaption><p>Please copy your given credentials and save them on your machine</p></figcaption></figure>

* Fly will create new fly.toml file within your application directory. If it doesn't please make it yourself.&#x20;
* It might ask you to use a Redis Deployment. Type `"N".`
* It will ask you to deploy your application? Type: `"N"`.&#x20;
* Alter the file `config/database.js` add in a production block that will be used to connect to your database when running Sequelize CLI commands. These env variables will be placed in our fly.toml file later on.  &#x20;

```javascript
require("dotenv").config();
module.exports = {
  development: {
    username: process.env.DB_USERNAME,
    password: process.env.DB_PASSWORD,
    database: process.env.DB_NAME,
    host: process.env.DB_HOST,
    dialect: process.env.DB_DIALECT,
  },
  production: {
    username: process.env.USERNAME,
    password: process.env.PASSWORD,
    database: process.env.DATABASE,
    host: process.env.HOST,
    dialect: process.env.DIALECT,
  },
};

```

* Alter your index.js within the model directory, we need to alter the Sequelize connection to connect to the newly deployed application. Replace the existing  Sequelize connection block with the block below, ensure that you alter the env environment to production as well. These environmental variables will be provided within the fly.toml file.&#x20;

<pre class="language-javascript"><code class="lang-javascript">const env = process.env.NODE_ENV || "production";
const config = require(__dirname + "/../../config/database.js")[env];
<strong>
</strong><strong>require('dotenv').config()
</strong><strong>if (process.env.DATABASE_URL) {
</strong>  sequelize = new Sequelize(
  process.env.DATABASE,
  process.env.USERNAME,
  process.env.PASSWORD,
  {
    host: process.env.HOST,
    dialect: process.env.DIALECT,
  }
);
} else if (config.use_env_variable) {
  sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
  sequelize = new Sequelize(
    config.database,
    config.username,
    config.password,
    config
  );
}
</code></pre>

* Alter the root index.js within this directory, we need to ensure that the application will use the environmental variables from fly, otherwise fly wont be able to test our application. Our backend must listen to port 3000 as this is what fly is expecting.&#x20;

```javascript
const PORT = process.env.PORT || 3000;
```

* Alter the fly.toml file that was created, add in a deploy release\_command, we will also need to set out our environmental variables for fly. Make up a Database name, this Database will be created, migrated and seeded.

```toml
 [build]
 
 [deploy]
  release_command = "sh ./release.sh"
 
 [env]
  PORT = "3000"
  USERNAME = "<Generated-Database-Username>"
  PASSWORD = "<Generated-Database-Password>"
  DATABASE = "<Database-Name>"
  HOST = "<Generated-Database-Host>"
  DIALECT = "postgres"
  NODE_ENV = "production"
  
[http_service]
  internal_port = 3000
  force_https = true
  auto_stop_machines = false
  auto_start_machines = true
  min_machines_running = 1
  processes = ["app"]
```

* <mark style="color:red;">Change the above from '\<Generated-.....> to the credentials that were given to you from fly.io when the database credentials were created above.</mark>
* <mark style="color:red;">The DATABASE here needs to match the one you created when running flyctl launch, fly.io generates a database name from the name of your app. I.E. bigfootsqlrocket-db</mark>
* <mark style="color:red;">NOTE: if you are hosting your own website you will need to add all of your .ENV variables into the toml.file</mark>
* At this point we need to update the .gitignore such that we do not send our fly.toml file online with our database credentials.&#x20;

### `release.sh`

* Create a `release.sh` file in the root of your project directory, within this file we need to place all the commands that will help us to setup our database, please create the file as below.

```shell
npx sequelize db:create
npx sequelize db:migrate
npx sequelize db:seed:all
```

We are able to run any CLI command from the `release.sh`, just make sure that you have installed the pre-requisite dependancies.&#x20;

### Dockerfile

When you ran `flyctl launch` a Dockerfile was generated, we will need to ensure that our  `release.sh` file is used an ran within the fly.io envrioment. Alter the Docker file to the file below:

```docker
FROM debian:bullseye as builder

ENV PATH=/usr/local/node/bin:$PATH
ARG NODE_VERSION=16.15.1

RUN apt-get update; apt install -y curl python-is-python3 pkg-config build-essential && \
    curl -sL https://github.com/nodenv/node-build/archive/master.tar.gz | tar xz -C /tmp/ && \
    /tmp/node-build-master/bin/node-build "${NODE_VERSION}" /usr/local/node && \
rm -rf /tmp/node-build-master

RUN mkdir /app
WORKDIR /app

COPY . .

RUN npm install

FROM debian:bullseye-slim

LABEL fly_launch_runtime="nodejs"

COPY --from=builder /usr/local/node /usr/local/node
COPY --from=builder /app /app
COPY release.sh /release.sh

WORKDIR /app
ENV NODE_ENV production
ENV PATH /usr/local/node/bin:$PATH

CMD [ "npm", "run", "start" ]
```

If a `.dockerignore` file has been generated please ensure that the `release.sh` and `fly.toml` file are not ignored.&#x20;

Run `flyctl deploy`, you are able to monitor the backend execution as well as the release commands through the fly.io dashboards.&#x20;

* Test our backend with Thunder Client! We should now be able to query our API server and retrieve results from our seed data.
* You can find the deployed backend url on your fly.io dashboard as seen in the images below.
* If this isn't working try to add in some secrets into the flyctl CLI

<figure><img src="/files/Apq8nFqOQE5QcbK5rwKt" alt=""><figcaption><p>Test our backend server with Thunder Client after fly deployment.</p></figcaption></figure>

<figure><img src="/files/6QzCLORBFAvf3CvTFCmO" alt=""><figcaption><p>fly.io dashboard of deployed applications</p></figcaption></figure>

<figure><img src="/files/CNLYZRgksSVHkM6xGWcO" alt=""><figcaption><p>Dashboard of deployed application, you can monitor from the tab on the left</p></figcaption></figure>

### Extra Reading

#### What is a fly.toml for?

The Fly.io platform makes use of the fly.toml to configure the application during deployment. Within the fly.toml file we can control the configuration of the build, any environmental variables, exposed resources as well as any release commands. In the example application that you have just deployed you added fly.toml environmental variables. The express application can now interface with the deployed database, using the environmental variables just added. We also got you to develop a shell file that would be run from the release command within the fly.toml. These shell command are run within the deployed environment setting up the database and seeding it.&#x20;

If you want to look in-depth at all of the configurations that you can create please have a read of [this set](https://fly.io/docs/reference/configuration/) of documentation.

## Frontend

To deploy your frontend application we will be using Netlify, you can either deploy your own version of the bigfoot-sql-frontend  or clone [this repo](https://github.com/rocketacademy/bigfoot-frontend-3.2/tree/deployment_example). After cloning you will need to get the correct branch, `deployment_example`, cd inside the cloned  directory and run the commands below:

`git fetch origin deployment_example`

`git checkout deployment_example`

Then you will need to install the required dependencies, following this you can run: `npm run dev`. After this open a browser and navigate to "<http://localhost:5173>".

### Context

We will deploy our frontends to a simple static site deployment service called Netlify to give us exposure to another static site deployment service. We are unable to deploy Bigfoot to GitHub Pages because GitHub Pages does not support frontend routing, and Netlify is simpler and just as popular as Firebase.

### Instructions

Update the `BACKEND_URL` we defined in `src/constants.js` from the Bigfoot JSON exercise to reference our deployed fly.io backend's URL in production. <mark style="color:red;">**This URL should be the one that is seen on the fly.io dashboard. So please replace URL in the code below with your own!**</mark> We can tell we're in production when the `NODE_ENV` environment variable is set to `"production"`. Rocket's `constants.js` looks like the following:

{% code title="constants.js" %}

```javascript
export const BACKEND_URL =
  process.env.NODE_ENV === "production"
    ? import.meta.env.VITE_SOME_BACKEND_URL
    : "http://localhost:3000";
```

{% endcode %}

Create a production build of the Application with `npm run build` from the Bigfoot Frontend repo folder. Then follow the ViteJs Netlify deploy instructions [to deploy](https://vitejs.dev/guide/static-deploy.html#netlify-cli). You may need to create a Netlify account if you don't have one already.

{% embed url="<https://docs.netlify.com/integrations/frameworks/vite/>" %}
Netlift and Vite
{% endembed %}

Install netlify globally onto your machine, if there is an error while running the command below, you may have some issue with user permissions, you can attempt to by pass this by prefixing the command above with the sudo.

`npm install -g netlify-cli`

Create a new site in Netlify on your CLI using the command&#x20;

`ntl init`

Choose follow these steps:

`Create & configure a new site`

`Choose a team if required` - Can be your own personal team

`Add a site name` - Note that you can leave this blank if you want netlify to generate one

`Authorise through github on netlify`

`Authorise netlify within the browser`

Define the correct build options

`Enter 'dist' folder as default publishing directory`

`Say Yes to make a netlify toml`

Build the latest version of your application

`npm run build`

Now you can deploy your site online

`ntl deploy --prod`

You should see something like this in your CLI window

<figure><img src="/files/S3exqIbdUMJIvXPXsnOr" alt=""><figcaption></figcaption></figure>

Note that we deployed site is [this one](https://bigfoot-frontend-3.netlify.app/).

That's it! The site should be up at the Website URL in the Netlify CLI output.

<mark style="color:red;">Note: If you are deploying your own website that uses auth0, you will need to alter the redirect URI and allowed callbacks to your deployed website.</mark>


# 3.E: Exercises


# 3.E.1: Bigfoot JSON

## Learning Objectives

1. Understand how to set up Express server to receive requests and respond with data
2. Understand how to set up CORS to allow access to server from different origin server

## Introduction

We will build an app that records and displays [Bigfoot](https://en.wikipedia.org/wiki/Bigfoot) sightings with an Express backend. We will build on this app in coming exercises to incorporate SQL and Sequelize.

## Setup

1. Fork and clone the [Rocket Academy Bigfoot JSON Backend repo](https://github.com/rocketacademy/bigfoot-json-backend-bootcamp)
2. Fork and clone the [Rocket Academy Bigfoot Frontend repo](https://github.com/rocketacademy/bigfoot-frontend-3.2)
3. Copy and paste `.env.sample` into the repository
4. Rename the duplicate file to `.env`
5. Change the `PORT` environment variable to 3000

## Base: Retrieve Sightings

### Starter Code

#### JSON Backend Repo

Rocket has provided starter code in `index.js` that responds to server requests to `/sightings` with all sighting data. The utilities module `utils.js` exports a function `getSightings` that reads sightings data from `sightings.json`. We are using `sightings.json` in lieu of a database because we have not yet learnt SQL, and in coming exercises we will replace `sightings.json` with a SQL database.

To run the backend server, install packages with `npm i` and run the script `node index.js`. This will start the server at `localhost:3000`.

#### Frontend Repo

Rocket has provided generic starter code for us to customise for Bigfoot. We will use this frontend repo for all Bigfoot exercises, even after switching to SQL in our backend.

To run the frontend repo, run `npm i` to install packages and `npm run dev` to compile our files and then open the browser of your choice at the site "<http://localhost5173".&#x20>;

### Retrieve sighting data in frontend from backend

1. Verify the backend API `/sightings` is working as expected by starting the backend server as per above instructions and sending a request to `localhost:3000` in Thunder Client. The API request  is `localhost:3000/sightings` it should respond with all sightings in JSON format.
2. Write code in our frontend app to query the backend API on component mount and render all sightings on the page. Feel free to only render basic info for each sighting such as year, season and month. Remember to store sightings in state, which will trigger a re-render, instead of trying to query the backend API on every render, which would be inefficient.
   1. If using `useEffect`, consider passing a [dependency array as a 2nd parameter](https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects) to `useEffect` to optimise performance and prevent unnecessary renders.
3. Add `cors` to our backend. Without `cors` we may notice that the data is not loading in our frontend, and we get the following error in our browser console: "Access to XMLHttpRequest at '<http://localhost:3000/>' from origin '<http://localhost:3001>' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource."

### Retrieve individual sighting data

Render basic sighting info for each sighting in the sightings list on the homepage. When we click on an individual sighting, navigate to a separate page that renders the full data for that specific sighting.

1. Create a new route in the backend `/sightings/:sightingIndex` that returns data for the sighting at the sighting index in URL params. Sighting index refers to the sighting's index in `sightings.json` in the backend.
2. Use React Router to implement frontend routing for the homepage and individual sighting pages, and include a back button on the individual sighting pages to go back to the homepage
   1. Consider using [nested routes](https://remix.run/docs/en/v1/guides/routing#what-is-nested-routing) to re-use UI logic, [URL params](https://reactrouter.com/en/6.6.1/hooks/use-params) to retrieve individual sighting indexes from URLs, and an [index route](https://reactrouter.com/en/main/route/route#index) to render the full sighting list. You can also use [useSearchParams](https://reactrouter.com/en/main/hooks/use-search-params) to update your frontend URL.
   2. Rocket recommends the frontend route `/sightings/:sightingIndex` for individual sighting routes for clarity of communication
   3. Consider using [`Link` components](https://reactrouter.com/en/6.6.1/components/link) to navigate between pages
3. When we navigate directly to the URL for an individual sighting, e.g. `localhost:5173/sightings/1`, render that specific sighting's page.

### Store backend URL in constant variable

We will store a single instance of our backend URL `BACKEND_URL` in a new file `constants.jsx` that we reference everywhere we need the backend URL. We do this because our backend URL will change depending on whether we run our app locally or in production, and we do not want to update a hard-coded backend URL in our code every time we switch between local and production environments, nor declare redundant logic to determine the correct backend URL in each component that uses the backend URL.

When we deploy our app to production in later exercises we can write logic in `constants.jsx` to set `BACKEND_URL` based on the value of Vitejs built-in environment variable [`import.meta.env.VITE_SOME_NODE_ENV`](https://vitejs.dev/guide/env-and-mode.html).  `NODE_ENV` will tell us which development environment we are in ("development", "test", or "production"), allowing us to set `BACKEND_URL` accordingly.

For now, create a new file `constants.jsx` and add the following content.

```javascript
export const BACKEND_URL = "http://localhost:3000";
```

Then update all references to `http://localhost:3000` in our components to import and use the `BACKEND_URL` constant variable.

## Comfortable: Filter Sightings

Create filter functionality in frontend UI that allows users to filter sightings by their attributes. For example, filtering by the year 1990 would render only sightings in 1990. Use [URL search params](https://reactrouter.com/en/6.6.1/hooks/use-params) to reflect filter settings in the URL.

Update the backend root route `/sightings` to retrieve only the filtered data (if there is a filter) using URL query parameters. Do not retrieve all sightings from the backend and filter on the frontend.

## More Comfortable: Sort Sightings

Create sort functionality in frontend UI that allows users to sort sightings by specified sighting attributes and in either ascending or descending order. Sorting should happen in addition to filtering. Feel free to perform sorting on either frontend or backend, and if sorting is on backend, send the sort parameters as query parameters like what we did with the filter feature.

## Submission

Submit pull requests to the `main` branches of Rocket's Bigfoot Frontend and Bigfoot JSON Backend repos respectively, and share your PR links in your section Slack channel.

There is no need to deploy this exercise for now. We will build on it in upcoming Bigfoot exercises and replace our JSON database with a SQL database before deploying.

## Reference Solution

Here is reference code for the [frontend](https://github.com/rocketacademy/bigfoot-frontend-3.2/tree/solution-json-base) and the [backend](https://github.com/rocketacademy/bigfoot-json-backend-bootcamp/blob/solution-base/index.js) for this exercise. You can do better!


# 3.E.2: Bigfoot SQL

## Learning Objectives

1. How to create a backend API server with Express, PostgreSQL and Sequelize
2. Connect a frontend app with a backend API server that uses SQL to store and retrieve data
3. Create a backend that supports the MVC structure

## Introduction

We will use forms and POST requests to save new Bigfoot sightings to our database.

## New Tooling: SQL Clients

SQL clients help us visualise our databases with clickable interfaces without repeatedly typing SQL queries. Rocket recommends using [DBeaver](https://dbeaver.io/) as a universal database management tool,  [pgAdmin](https://www.pgadmin.org/) for Windows specific software and [Postico](https://eggerapps.at/postico/) for Mac specific software, all of which are free. You are free to use any other SQL clients you may prefer.

1. Universal tool: [DBeaver downloader](https://dbeaver.io/download/)
   1. For further instructions on DBeaver please refer to this [section](/3-backend/3.2-sql/3.2.6-dbeaver).
2. Windows: [pgAdmin installation instructions](https://stackoverflow.com/questions/45707319/pgadmin-on-windows-10-with-postgres-when-installed-via-bash-on-ubuntu-on-windows/54192456#54192456)
3. Mac: [Postico installation instructions](https://eggerapps.at/postico/)

## \[Reference Only] Sequelize Setup

Rocket has performed the following Sequelize setup for this Bigfoot exercise, but you may wish to refer back to these instructions for future projects where you need to set up Sequelize on your own.

### Setup Packages

#### Install Sequelize NPM Packages

Install `sequelize` and `pg` to use Sequelize with Postgres in our app.

```
npm i sequelize pg
```

Install `sequelize-cli` in dev dependencies to generate Sequelize model and migration files and run Sequelize migrations that will set up our database schema. We install to dev dependencies because we only need `sequelize-cli` for database setup and not when the app is live; dev dependencies are typically not installed in production. The `-D` flag is for dev dependencies.

```
npm i -D sequelize-cli
```

#### Create Sequelize Folders

Create a `.sequelizerc` file in the root of our repo to tell Sequelize where to store its files. We will use a suggested configuration from the official Sequelize docs.

{% code title=".sequelizerc" %}

```javascript
const path = require("path");

module.exports = {
  config: path.resolve("config", "database.js"),
  "models-path": path.resolve("db", "models"),
  "seeders-path": path.resolve("db", "seeders"),
  "migrations-path": path.resolve("db", "migrations"),
};
```

{% endcode %}

Create Sequelize folders and starter files in the locations specified in `.sequelizerc` using `npx sequelize init`. These will store Sequelize files and configurations that we will need for our application. We will explore these files in more detail below.

```bash
npx sequelize init
```

Verify our Sequelize config file is in `config/database.js` and our `models`, `seeders` and `migrations` folders are in a folder called `db`.

### Configure Database

#### Populate DB config

Update `config/database.js` to contain database settings for the "development" environment, i.e. when we are developing locally. We can delete "test" and "production" settings for now until we need them.

{% code title="config/database.js" %}

```javascript
module.exports = {
  "development": {
    "username": "my_unix_username",
    "password": null,
    "database": "my_app_development",
    "host": "127.0.0.1",
    "dialect": "postgres"
  }
}
```

{% endcode %}

Replace `my_unix_username` with your local Unix username (use `whoami` to find it) and replace `my_app` in `my_app_development` with the name of your app in snake\_case. To mask this sensitive data we suggest using a .env within your application for a refresher have a look [here](https://bootcamp.rocketacademy.co/2-full-stack/2.2-advanced-react/2.2.7-environmental-variables).&#x20;

**Create DB based on config**

Create the database specified in the config using Sequelize CLI's `db:create` command.

```
npx sequelize db:create
```

We should see output like the following after creating our database on the command line.

```
Sequelize CLI [Node: 16.14.2, CLI: 6.4.1, ORM: 6.20.1]

Loaded configuration file "config/database.js".
Using environment "development".
Database my_app_development created.
```

### Create Models and Migrations

Recall from Rocket's Sequelize submodule that models tell our apps what data they can access, and migrations control our database schema. Our models may change as our apps evolve, and we will need to create new migrations to update our databases with those changes without affecting live data.

#### Create model and migration files

Use Sequelize's `model:generate` command to generate a model and initial migration for the `Sighting` model (and `sightings` table in our DB). We use data type `text` for the `notes` field because notes can be longer than 255 chars, which is the max length for data type `string`.

```
npx sequelize model:generate --name sighting --attributes date:date,location:string,notes:text --underscored
```

This should generate output like the following.

```
Sequelize CLI [Node: 16.14.2, CLI: 6.4.1, ORM: 6.20.1]

New model was created at /Users/kai/rocket-code/bootcamp/examples/bigfoot-sql-backend-bootcamp/db/models/sighting.js .
New migration was created at /Users/kai/rocket-code/bootcamp/examples/bigfoot-sql-backend-bootcamp/db/migrations/20220531155824-create-sighting.js .\
```

### **Run Migration to Create Table**

Migration files specify what changes Sequelize should make to our DB schema. To execute all unexecuted migration files, run Sequelize CLI's `db:migrate` command.

```
npx sequelize db:migrate
```

`db:migrate` will perform the following.

1. Create a table called SequelizeMeta in database if it doesn't exist yet that records which migrations have run on the database so far
2. Run migration files that have not been run yet, generating relevant tables and columns

### Create and Run Seeder to Populate Database

Seed files specify what seed data to include in our database before any user input. In our case we will populate dummy sighting data so the app does not look empty when users open it.

#### Generate seed file

Run Sequelize CLI's `seed:generate` command to generate a new seed file. Use kebab-case for the seed file name by convention.

```
npx sequelize seed:generate --name seed-sightings
```

This should generate output like the following.

```
Sequelize CLI [Node: 16.14.2, CLI: 6.4.1, ORM: 6.20.1]

seeders folder at "/Users/kai/rocket-code/bootcamp/examples/bigfoot-sql-backend-bootcamp/db/seeders" already exists.
New seed was created at /Users/kai/rocket-code/bootcamp/examples/bigfoot-sql-backend-bootcamp/db/seeders/20220601140735-seed-sightings.js .
```

Notice we have a new seed file in our `db/seeders` folder. The file should have the following contents.

{% code title="20220601140735-sightings.js" %}

```javascript
"use strict";

module.exports = {
  async up(queryInterface, Sequelize) {
    /**
     * Add seed commands here.
     *
     * Example:
     * await queryInterface.bulkInsert('People', [{
     *   name: 'John Doe',
     *   isBetaMember: false
     * }], {});
     */
  },

  async down(queryInterface, Sequelize) {
    /**
     * Add commands to revert seed here.
     *
     * Example:
     * await queryInterface.bulkDelete('People', null, {});
     */
  },
};
```

{% endcode %}

#### Populate seed file

We will edit this file to insert sightings. Notice the structure of the file is similar to migration files, where Sequelize runs `up` to apply the seeder and `down` to undo the seeder. We will rarely use `down` but we should still include the relevant code to undo our `up` logic in case needed.

Notice the example seed code in the auto-generated comments references [`queryInterface.bulkInsert`](https://sequelize.org/api/v6/class/src/dialects/abstract/query-interface.js~queryinterface#instance-method-bulkInsert) and [`queryInterface.bulkDelete`](https://sequelize.org/api/v6/class/src/dialects/abstract/query-interface.js~queryinterface#instance-method-bulkDelete) commands. We will be using these methods to insert and delete our seeders respectively. All `queryInterface` methods have detailed documentation in Sequelize API docs.

After collecting data from `sightings.json` in the Bigfoot JSON exercise, our new seeder file now looks like the following.

{% code title="20220601140735-sightings.js" overflow="wrap" %}

```javascript
"use strict";

module.exports = {
  async up(queryInterface, Sequelize) {
    await queryInterface.bulkInsert(
      "sightings",
      [
        {
          date: new Date(1990, 9),
          location: "East side of Prince William Sound, Alaska, USA",
          notes:
            "Ed L. was salmon fishing with a companion in Prince William Sound. After anchoring off shore, his companion took a small boat up a river to check on the state of the salmon run. As the day wore on toward evening and he didn't come back at the expected time, Ed scanned upriver and across the adjacent land with binoculars. There he saw a sasquatch walking across the tundra, with long, smooth steps and with dark hair flowing from its shoulders, bouncing behind \"like a cape\" at every step. The sasquatch paid no attention to the boat (distance about 1,000').",
          createdAt: new Date(),
          updatedAt: new Date(),
        },
        {
          date: new Date(2000, 9, 2),
          location: "Warren County, New Jersey, USA",
          notes:
            "a month ago i was with a friend and her son, we were hanging out at a camp ground by Allamuchy state park, in Warren county NJ. i think the camp ground was part of Stephens state park either way it was on the Musconetcong river. it was late in the day and we were just walking on the trials by the river. then i heard a sound like someone was lightly banging a fork or something against a plate. i thought maybe a bear was snooping around looking for a free meal, this is bear country and we have a very healthy black bear population, but maybe 30 seconds after i heard the metalic sound i heard someone or something bang a branch against a tree 4 or 5 times in a row, i thought that the bear maybe was getting a little to close to someones camp site. i didnt smell anything but i think i was up wind anyway and we were burning wood in the fire and all i could really smell was the fire anyway. it also bothers me that something waited until it was sure that i was asleep before coming into camp. i looked around before we left to see if i could find any tracks or anything but the ground is was just to hard, there was a few game trails but i didnt look very far or spend alot of time looking. i looked on the internet and found this sight and was surprized to see other sitings in new jersey.",
          createdAt: new Date(),
          updatedAt: new Date(),
        },
        {
          date: new Date(2016, 6, 7),
          location: "Sullivan County, New Hampshire, USA",
          notes:
            "I was on my way to Claremont from Lebanon on Rte 120 and was passing by some reeds in a marshy area next to the road that sounded like a huge flock of birds. The creature came out of the reeds and was crouched down looking at me through them. Surprisingly it got out of the reeds from crouched to standing turned around and ran towards the wooded area up a hill and was moving with it's arms brush and tree branches out of the way. It was incredibly fast runner and I got a good look at its coconut shaped head as it ran away. It was light brown/brown. It had incredibly broad shoulders. I went back the same day. The marsh went up to my knees and I could smell a bad odor like garbage. Myself and a friend went back to the sighting. We found a footprint and a hair sample. I could hear wood knocks when my friend James did a call and we also found a large bed of branches and some tree structures. The following month I went back to Claremont and I heard screeching in the woods while I was traveling Rte. 120 on a bicycle.",
          createdAt: new Date(),
          updatedAt: new Date(),
        },
      ],
      {}
    );
  },

  async down(queryInterface, Sequelize) {
    await queryInterface.bulkDelete("sightings", null, {});
  },
};
```

{% endcode %}

#### Run seed file to populate database

Run our seed file with Sequelize CLI's `db:seed:all` command to populate our database with our seed data.

```
npx sequelize db:seed:all
```

This should generate output like the following.

```
Sequelize CLI [Node: 16.14.2, CLI: 6.4.1, ORM: 6.20.1]

Loaded configuration file "config/database.js".
Using environment "development".
== 20220601140735-sightings: migrating =======
== 20220601140735-sightings: migrated (0.006s)
```

## Exercise Setup

### Fork and clone repos

1. Fork and clone the [Rocket Academy Bigfoot SQL Backend repo](https://github.com/rocketacademy/bigfoot-sql-backend-bootcamp)
2. Continue with your forked copy of the Rocket Academy Bigfoot Frontend repo from the Bigfoot JSON exercise
3. While developing within the Backend repo follow the MVC pattern.&#x20;

### Familiarise yourself with starter code

Rocket has set up Sequelize for us using the steps documented above. Familiarise yourself with those steps and the files in the starter code for when you need to set up Sequelize for yourself in your projects.&#x20;

### Setup backend

#### Instructions

1. Run `npm i` from the root of the Bigfoot SQL Backend repo to install relevant packages
2. Create your .env based off the sample provided from the exercise repo.
3. Update `config/database.js` to use your Unix username and name the database `bigfoot_sql_development`. Kai's looks like the one below.
4. Run `npx sequelize db:create` to create the `bigfoot_app_development` database
5. Run `npx sequelize db:migrate` to set up the database schema
6. Run `npx sequelize db:seed:all` to seed data in the database
7. Verify the seed data was added by viewing the `sightings` table in your chosen SQL client. You can use the information in `config/database.json` to connect to the database in the SQL client.

#### Sample `database.js`

{% code title="config/database.js" %}

```json
require('dotenv').config()

module.exports = {
  "development": {
    "username": process.env.DB_USERNAME,
    "password": process.env.DB_PASSWORD,
    "database": process.env.DB_NAME,
    "host": process.env.DB_HOST,
    "dialect": process.env.DB_DIALECT
  }
}
```

{% endcode %}

#### Sample view of `sightings` table in Postico

![Sample view of Sightings table in Postico after running migrations and seeders](/files/WZ8LjCvG6Otp4NAtThf7)

## Base: Report New Sightings

Allow users to report Bigfoot sightings that are saved to our SQL database. When users refresh the sightings page they should be able to see the sightings they added.

### Verify with Thunder Client that backend routes work

Rocket provided starter routes in `index.js` that import the `Sighting` Sequelize model and query it for data. We will first verify those routes work with Thunder Client before attempting to connect the backend to the frontend.

#### Verify root route returns all sightings

1. Start the API server with `npm start` from the root of the Bigfoot SQL Backend repo
2. Open Thunder Client in VS Code and send a request to `localhost:3000/sightings`
3. Verify that we receive the 3 sightings we seeded in our database

![Sample request to localhost:3000/sightings with Thunder Client](/files/LpRNlFw3Du8pv9gZV1vc)

#### Verify sighting-specific route returns data for single sighting

1. Start the API server with `npm start` from the root of the Bigfoot SQL Backend repo
2. Send a request to `localhost:3000/sightings/1` in Thunder Client
3. Verify we receive the data for the first sighting in our database

#### Understand the backend architecture

The index.js is the entry point to our application and any request made from the browser to our backend server will go through this file. Within the boilerplate code a SightingRouter and SightingController are used to send responses to frontend API requests that you can test as above. These files help to maintain the applications structure as we develop further. The routers are used to define the url endpoint the frontend can consume, while the controllers query the Sequelize data for reference or alter it, if requested. The request is handled by the index, which is passes the request to the appropriate router, before the correct controller method is chosen and an output is used as a response.&#x20;

### Connect backend to frontend to view sighting data

Connect the backend we just set up with our frontend from Bigfoot JSON to achieve the same functionality we had before.&#x20;

1. Start the backend server with `npm start`
2. Start the frontend server with `npm start` from the root of the Bigfoot Frontend repo
3. Tweak the logic in the frontend to show only the `date` and `location` properties of each sighting on the homepage and `date`, `location` and `notes` properties of each sighting on sighting-specific pages

{% hint style="warning" %}
**Using sighting ID instead of array index to reference individual sightings**

In Bigfoot JSON we may have used array index to reference specific sightings, e.g. when we navigate to a sighting-specific page. Now that we store our sightings in SQL, we will want to use the SQL `id` property of each sighting instead.

Rocket recommends renaming all mentions of sighting index to sighting ID instead for clarity.
{% endhint %}

### Create backend route to create new sighting

1. Add [Express JSON middleware](https://expressjs.com/en/api.html#express.json) using `app.use(express.json());` above our routes in `index.js` to enable Express to parse JSON bodies of incoming POST requests
2. Create a route for a POST request to `/sightings` to create a new sighting in our database using Sequelize and return the new sighting with `res.json`. We can access request body attributes using `req.body`.
   1. Follow the MVC setup within the boilerplate
   2. Create a new method within the `SightingsController` class, `controllers/sightingsController.js` that contains the logic to add a new sighting into the `sighting` table.&#x20;
   3. Create a new route within the routes() method within the `SightingsRouter` class, bind the new method that you created in the previous step with the class itself.
   4. Note we design our API to send a POST request to `/sightings` instead of paths like `/createSighting` because [REST API best practices](https://stackoverflow.blog/2020/03/02/best-practices-for-rest-api-design/#h-use-nouns-instead-of-verbs-in-endpoint-paths) suggest using nouns instead of verbs in paths, using request method to communicate type of action
3. Verify our route works by sending a POST request with Thunder Client to `localhost:3000/sightings` with the relevant new sighting data in a JSON body

Your Thunder Client output may look something like the following.

![POST request to our API server at localhost:3000/sightings with Thunder Client](/files/ds96J41C2hWcRKHHIZp4)

### Create new page on frontend to input new sighting

1. Create new frontend route `/new` in `index.js` in the Bigfoot Frontend repo where we will render our new sighting form component
2. Create new component for new sighting form in the `components` folder and import it in `index.js` where we can render it for the `/new` frontend route. This component should render a sighting form that sends a POST request to our API server on submit and redirect to the sighting-specific route for the new sighting after submit.
   1. Reminder to use controlled form inputs to manage forms in React
   2. Consider using the [HTML `input` type `datetime-local`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/datetime-local) to input dates and times compatible with our Sequelize DATE data type
   3. [Here is Axios POST request syntax](https://axios-http.com/docs/post_example) for reference
   4. Reminder to use the `BACKEND_URL` constant we defined in Bigfoot JSON to access our backend, instead of hard-coding the backend URL, which would make our code more prone to bugs.
   5. Consider using [React Router's `useNavigate` hook and `navigate` function](https://reactrouter.com/docs/en/v6/getting-started/overview#navigation) to navigate to the sighting-specific page after form submit. Navigate after the `axios` promise resolves so that when we reach the sighting-specific page our app will be able to retrieve the new sighting from the database. Retrieve the sighting ID of the new sighting from the response to our POST request at `res.data`.&#x20;
3. Create a link at the root route `/` that navigates users to `/new` to submit a new sighting. Consider using [React Router's `Link` component](https://reactrouter.com/docs/en/v6/getting-started/overview#navigation) for this, and consider creating a new component to encapsulate both the new sighting button and sighting list to render at the `/` route in `index.js`.

## Comfortable: Edit Sightings

1. Create an edit sighting route in the backend that accepts PUT requests to `/sightings/:sightingId`. Requests to this route should update the relevant sighting's data in the database and return the full sighting data to the client, similar to the POST route to create a new sighting. Test the new route in Thunder Client before moving on.
   1. Follow the MVC setup within the boilerplate
   2. Create a new method within the SightingsController, `controllers/sightingsController.js` that contains the logic to edit a particular sighting within the `sighting` table. Use the `put` not `post`
   3. Create a new route within the routes() method within the `SightingsRouter` class, bind the new method that you created in the previous step with the class itself.
2. Create an edit sighting form in the frontend at `/sightings/:sightingId/edit` that automatically pre-populates with that sighting's data in the backend. Submitting the form should save the sighting's new data in the backend and redirect to the sighting-specific page, similar to functionality of the new sighting form.
3. Create a link on sighting-specific pages to edit that sighting. That link should navigate to the edit sighting form for that sighting.

## More Comfortable: Add Location Details

1. Update our `Sighting` model in the backend to include location properties such as `city` and `country`, and rename the `location` property to `locationDescription` for clarity
2. Create a new migration using Sequelize CLI's `migration:generate` function to add `city` and `country` columns to the `Sightings` table and update the `location` column name to `locationDescription`. Remember to add a `down` function in the migration to undo the migration. Use the existing migration as a reference; you may find the [Sequelize `queryInterface` API docs](https://sequelize.org/api/v6/class/src/dialects/abstract/query-interface.js~queryinterface) helpful.
3. Update new sighting form and edit sighting form in the frontend to accept city and country data and send location description data correctly, updating field names where relevant

## Submission

Submit pull requests to the `main` branches of Rocket's Bigfoot Frontend and Bigfoot SQL Backend repos respectively, and share your PR links in your section Slack channel.

There is no need to deploy this exercise for now. We will build on it in upcoming Bigfoot exercises and deploy at the end of Bigfoot SQL M-M exercise after we have a firmer grasp of Sequelize.

## Reference Solution

Here is reference code for the [frontend](https://github.com/rocketacademy/bigfoot-frontend-3.2/tree/solution-sql-base) and the [backend](https://github.com/rocketacademy/bigfoot-sql-backend-bootcamp/blob/solution-sql-base/index.js) for this exercise. You can do better!


# 3.E.3: Bigfoot SQL 1-M

## Learning Objectives

1. How to create and update models and migrations to add models with 1-M relationships to our applications
2. Understand the development process of creating and updating models and migrations, creating and testing backend routes, and creating and testing frontend functionality. Always develop with user stories in mind.

## Introduction

We will add a comments feature to Bigfoot so users can leave comments on each sighting. There will be a 1-M relationship between sightings and comments respectively.

## Setup

If you haven't already, complete Exercise Setup for the previous Bigfoot SQL exercise. This exercise will use the same frontend and backend repos and the same setup. Remember to follow the MVC set up, so create Controllers and Routers within your backend repository.

## Base: Add Comments to Sightings

### Create `Comment` model, associate with `Sighting`

#### Create model and migration files

Create a new model `Comment` to store comments with [`npx sequelize model:generate`](https://sequelize.org/docs/v6/other-topics/migrations/#creating-the-first-model-and-migration), which will also create a corresponding migration. `Comment` should have `content` and `SightingId` attributes, where `content` can be `text` data type and `SightingId` can be `integer`. No need to input `references` attribute for the foreign key yet; we can edit our model and migration files after they are created. You may need to add in the model constraint `underscored: true`.&#x20;

```
npx sequelize model:generate --name comment --attributes content:string,sighting_id:integer
```

This should generate output like the following.

```
Sequelize CLI [Node: 16.14.2, CLI: 6.4.1, ORM: 6.20.1]

New model was created at /Users/kai/rocket-code/bootcamp/examples/bigfoot-sql-backend-bootcamp/db/models/comment.js .
New migration was created at /Users/kai/rocket-code/bootcamp/examples/bigfoot-sql-backend-bootcamp/db/migrations/20220604082051-create-comment.js .
```

#### Update model and migration files to include associations and foreign key attributes

Add associations and foreign key declarations to `Sighting` and `Comment` models. Review Update models and migrations section of Sequelize 1-M Relationships submodule for a refresher.

Add foreign key declaration to `comment` migration by adding the `references` attribute to `sighting_id`.

#### Run migrations and verify schema correctness

Run migrations to create the `comments` table in our database as we specified in the migration. Verify that our migrations succeeded by viewing the new `comments` table in either DBeaver,  pgAdmin or Postico and verifying that our `content` and `sighting_id` attributes were included successfully.

![Sample empty Comments table in Postico after running migrations](/files/vGEu1doAuAUyvN2KFIrT)

Congrats! We're now ready to use our new database structure in our application!

### Write backend routes for comments

Now that we've updated our models and database schema to include comments, let's write routes to retrieve and create comments so that our frontend can store and retrieve comment data in the backend.

#### Add routes to retrieve and create comments

In `/controllers/sightingsController.js` add two new methods to the class `SightingController`, one with the logic that will be used to retrieve all comments from a sighting, and the other to create comments on sighting.&#x20;

In `/routers/sightingsRouter.js`, add 2 new routes for retrieving and creating comments for a given sighting respectively.&#x20;

Consider using the `/sightings/:sightingId/comments` path and GET method to retrieve comments, and the `/sightings/:sightingId/comments` path and POST method to create a comment. Notice we are using [REST API best practices](https://stackoverflow.blog/2020/03/02/best-practices-for-rest-api-design/#h-use-nouns-instead-of-verbs-in-endpoint-paths) to name route paths, aiming to name paths with nouns and use HTTP methods to communicate actions.&#x20;

There are multiple ways to query for all comments or create a new comment for a given sighting. Rocket recommends specifying `sighting_id` in `findAll` and `create` methods to perform each route's logic in a single query instead of multiple.

#### Test new routes with Thunder Client

After creating the 2 routes, test them with Thunder Client to make sure they are working before moving on. The following screenshot demonstrates a successful POST request to `/sightings/:sightingId/comments`.

![Sample POST request to /sightings/:sightingId/comments from Thunder Client](/files/4osFtXqyuXO37IZIx9XM)

Almost there! Time to hook up the frontend!

### Add comment list and input interfaces to sighting-specific pages

We will edit our sighting-specific page in our frontend to render a list of comments for that sighting and render a composer above that list to leave new comments.

#### Render comment list

Update the component we are using for our sighting-specific page to retrieve all comments for that sighting on component mount (likely in `useEffect`), save those comments in state and render those comments below sighting details. Feel free to use any UI elements you prefer; Rocket uses a [React Bootstrap `ListGroup`](https://react-bootstrap.github.io/components/list-group/) in our reference solution.

#### Render comment composer

Create a form below sighting details and above the comment list to create new comments. On submit, this form should send an AJAX POST request to our `/sightings/:sightingId/comments` API to save the comment in the database. After successfully creating the new comment, retrieve all comments with the `/sightings/:sightingId/comments` GET API to refresh the local comment list. Feel free to use any UI elements you prefer; Rocket uses a React Bootstrap `Form` in our reference solution.

{% hint style="info" %}
**Creating new comment is similar to creating new sighting**

The pattern for creating a new comment should be similar to creating a new sighting. Feel free to review your old code for reference!
{% endhint %}

Congratulations on making it this far!!!

## Comfortable: Edit and Delete Comments

1. Create edit and delete comment routes in the backend that accept PUT and DELETE requests respectively. Requests to the edit route should respond with the edited comment instance, and requests to the delete route should respond with no data.&#x20;
   1. Follow the MVC setup within the boilerplate
   2. Create new methods within the `SightingsController` class, `controllers/sightingsController.js`
   3. Create new routes within the routes() method within the `SightingsRouter` class, bind the new method that you created in the previous step with the class itself.
   4. Test the new routes with Thunder Client before moving on.
2. Create an edit comment form in the frontend that auto-populates with the relevant comment's content and on submit sends a PUT request to our edit comment route. We may wish to create this form in its own component for decomposition.
3. Create edit and delete buttons next to each comment that allow users to edit and delete comments. The edit button should toggle the edit comment form to appear and disappear. The delete button should send a request to our delete route and on successful delete, remove the relevant comment from the frontend. After edit or delete, consider querying for all comments again like after we created a new comment to refresh the comment list with most updated data.

## More Comfortable: Add Likes on Sightings

1. Create a new model `Likes` with a 1-M relationship with `Sightings`, where each sighting can have many likes, but each like belongs to a single sighting. Update models and migrations like we did with comments such that our Express app can use Sequelize relationship methods with the `Like` model.
2. Create routes & controller methods to retrieve and create likes for a given sighting, similar to what we did with comments. Link the new methods to the router within sightingRouter.js Test these routes with Thunder Client before moving on.
3. Update our frontend to display the number of likes each sighting has and enable users to like sightings. Because we haven't implemented authentication yet, users can like sightings unlimited times.

## Submission

Submit pull requests to the `main` branches of Rocket's Bigfoot Frontend and Bigfoot SQL Backend repos respectively, and share your PR links in your section Slack channel.

There is no need to deploy this exercise for now. We will build on it in upcoming Bigfoot exercises and deploy at the end of Bigfoot SQL M-M exercise after we have a firmer grasp of Sequelize.

## Reference Solution

Here is reference code for the [frontend](https://github.com/rocketacademy/bigfoot-frontend-3.2/tree/solution-sql-1-m-base) and the [backend](https://github.com/rocketacademy/bigfoot-sql-backend-bootcamp/tree/solution-sql-1-m-base) for this exercise. You can do better!


# 3.E.4: Bigfoot SQL M-M

## Learning Objectives

1. Understand how to set up M-M relationships in a SQL database using models and migrations with foreign keys and junction tables
2. Understand how to query M-M relationship data with Sequelize
3. Understand how to input M-M relationship data in an app

## Introduction

We will add some weather categories to our Bigfoot sightings to make it easier for researchers to categorise sighting data. These weather categories could include values like 'Sunny', 'Raining' or even 'Snowing'. There will be an M-M relationship between categories and sightings.

## Setup

If you haven't already, complete Exercise Setup for the prior Bigfoot SQL exercise. This exercise will use the same frontend and backend repos and the same setup. Remember to follow the MVC setup, create a new Controller and Router to support the Category Model.

## Base: Add Categories to Sightings

We will follow a similar workflow to Bigfoot SQL 1-M in adding a new model, routes and frontend elements to support the categories feature.

### Create `Category` model, associate with `Sighting`

#### Create new model and add associations

Create a new model `Category` to store sighting categories with `npx sequelize model:generate`, which will also create a corresponding migration. Reminder that our model names are Title Case with first letter capitalised. `Category` should have a `name` attribute of type `string`.

Update `Category` and `Sighting` models to include a `belongsToMany` association from each to the other, using the `through` option to specify junction table name `sighting_categories`.

#### Create migration for junction table

Create a new migration file for the `sighting_categories` junction table with `npx sequelize migration:generate`. Name the migration file with the same convention as the previous migration files, e.g. `create-sightingcategories`.

Update the migration for `sighting_categories` to create the junction table with `id`, `sighting_id`, `category_id`, `created_at` and `updated_at` attributes. Reference past migration files for `sightings` and `comments` tables for format of boilerplate attributes like `id`, `created_at` and `updated_at` and foreign key attributes like `sighting_id` and `category_id`. Remember to include the reverse instructions to drop the table in the `down` function, and verify our table name strings are accurate.

#### Run migrations

Run migrations with `npx sequelize db:migrate` and verify in our SQL client that our tables are what we expect. This would be a good time to commit changes to keep our commits small and with the app in working condition. Remember to include a short and descriptive commit message.

### Write backend routes for categories

#### Clarify app requirements before creating backend routes

Before we start writing routes, let's understand app requirements and decide on inputs and outputs for our categories APIs.

We will need to add and remove categories when creating or editing sightings. We will use the [React Select library](https://react-select.com/home) in our frontend for users to select categories.

The above requirements mean we need 2 new routes: one to retrieve all categories and another to create a new category. We will also need to update our sighting creation route and sighting edit route (if any) to associate specified categories with sightings.

Let's start by creating the new routes to retrieve and create categories.

#### Create routes to retrieve and create categories

You will also need to create an additional controller, the categoriesController.js that should extend the base controller and be populated with the methods that will power facilitate category alterations to our database. In this case, you will need a method to create a new category instance, remember, as you are extending the base controller you have access to its method.

Create a new router file named categoriesRouter.js, model the sightingsRouter.js, create two requests, one a GET route to `/categories` to retrieve categories and a POST route to `/categories` to create a new category, the post route should read the category name from `req.body.name`. Ensure you bind these requests to the correct controller methods that you have just defined.

Besure to import the new categoriesRouter and categoriesController into the `index.js` and set up the middleware required to route our http requests, model how the sightingRouter and sightingController are implemented within the `index.js`.

#### Update sighting creation and edit routes (if any) to associate relevant categories with the relevant sighting

We want to remove associations with any no-longer-associated categories and add associations to all newly-associated categories. Luckily, [Sequelize `belongsToMany` relationship methods](https://sequelize.org/docs/v6/core-concepts/assocs/#foobelongstomanybar--through-baz-) provide us a convenient `fooInstance.setBars()` relationship method to do exactly this.

Unfortunately we are not yet sure exactly in what format our frontend will send category IDs to our backend, so let's come back to this task later.

#### Test routes with Thunder Client

Test that our GET and POST routes to `/categories` work with Thunder Client before moving on.

### Update frontend to select categories on sighting creation

Update our new sighting form to add a categories field powered by [React Select](https://react-select.com/home). React Select will provide a controlled form input whose value we control with a state variable. On form submit we will send the value of the state variable to our backend just like all other form inputs.

#### Add categories to database using POST requests with Thunder Client

To make our form more realistic, add at least 3 categories to our database via a new seeder file. We can generate the seeder file with `npx sequelize seed:generate --name categories` and populate the seeder file with content following the same format as our `sightings` seeder file. These categories can be `rain`, `mountain`, `woods` or any other categories you deem relevant.

#### Enable users to select categories with React Select

Install `react-select` as per [React Select's Getting Started docs](https://react-select.com/home#getting-started).

Include `Select` as a form field in our new sighting form. Rocket's reference implementation looks like the following.

{% code title="NewSightingForm.js" %}

```jsx
<Select
  isMulti
  options={categoryOptions}
  value={selectedCategories}
  onChange={handleSelectChange}
/>
```

{% endcode %}

1. `isMulti` tells `Select` to accept multiple inputs
2. `options` are the category options in our select field that we retrieve with `useEffect`. Remember to pass `[]` as 2nd param to `useEffect` so the effect only runs on component mount!
3. `value` is the local state we use to control this form field. `selectedCategories` is local state we created with `useState`.
4. `onChange` is the callback method we use to update local state when the value of the select field changes. Unlike `onChange` for regular HTML input fields, `onChange` for React Select passes an array of selected values in `{ value, label }` format as the 1st parameter to the callback function. This means we will need to create a custom `handleSelectChange` function separate from any `handleChange` functions we created for the other input fields. React Select `onChange` [API documentation here](https://react-select.com/props#api) (search for "onChange").

Rocket also included the following `useEffect` hook and logic to generate category options that may be helpful for you. `allCategories` is local state we created with `useState`.

{% code title="NewSightingForm.js" %}

```jsx
useEffect(() => {
  axios.get(`${BACKEND_URL}/categories`).then((response) => {
    setAllCategories(response.data);
  });
  // Only run this effect on component mount
}, []);

const categoryOptions = allCategories.map((category) => ({
  // value is what we store
  value: category.id,
  // label is what we display
  label: category.name,
}));
```

{% endcode %}

Implement the above first, run our backend and frontend servers locally and verify we can receive all category options in our select field.

{% hint style="info" %}
**Control `Select` field colours**

If you find that the `Select` field's colours are off, e.g. white text on white background, you can customise the `Select` field's styles relatively easily.

Rocket created the following `Select` style object in our sighting creation form.

```jsx
// Make text black in Select field
const selectFieldStyles = {
  option: (provided) => ({
    ...provided,
    color: "black",
  }),
};
```

We then applied that style to our `Select` element like below.

```jsx
<Select
  isMulti
  styles={selectFieldStyles}
  options={categoryOptions}
  value={selectedCategories}
  onChange={handleSelectChange}
/>
```

[React Select's styling documentation](https://react-select.com/styles#provided-styles-and-state) provides a quick overview.
{% endhint %}

#### Update frontend and backend submit logic to create new sightings with category associations

Update our `handleSubmit` function to include selected category IDs when submitting new sighting data to our backend.

We now know our backend POST route to `/categories` will receive categories as an array of category IDs and can complete that route. In the route middleware function, retrieve relevant categories (you may find [this Stack Overflow answer](https://stackoverflow.com/a/25028339) helpful) and associate them with the new sighting with the Sequelize `belongsToMany` `fooInstance.setBars()` (i.e. `newSighting.setCategories()`) relationship method.

Verify we can associate the new sighting with categories on submit. Great work!

### Display categories next to sightings

Last but not least, let's display any associated categories next to sightings on the home page and the sighting-specific page.

#### Update routes to retrieve sightings to also retrieve category data

Update our backend routes that retrieve sightings (`/sightings` and `/sightings/:sightingId`) to also retrieve associated categories. We can do this with eager loading by specifying `include: Category` as query option. Review Sequelize's [introduction to eager loading](https://sequelize.org/docs/v6/core-concepts/assocs/#fetching-associations---eager-loading-vs-lazy-loading) and [`findByPk` API reference](https://sequelize.org/api/v6/class/src/model.js~model#static-method-findByPk) for examples and docs.

Verify with Thunder Client that these routes return category data together with sighting data.

#### Display category data next to sightings on homepage and sighting-specific page

Almost there! Now that our sighting retrieval routes respond with category data, update our UI logic to render associated categories next to each sighting on the homepage and sighting-specific pages. Congratulations!

## Comfortable: Create New Categories

Use [React Select Creatable](https://react-select.com/home#creatable) features to allow users to create new categories while selecting categories. This may involve making an AJAX POST request to `/categories` in our `Select` field's `onChange` handler function to create a new category in the database, such that when we submit the category from our frontend, our backend can associate that category with the relevant sighting.

## More Comfortable: Add Category Intensity

Add a non-foreign-key junction table column `intensity` to describe the intensity of each weather category associated to the sighting. Some values could include: 'heavy', 'light' and 'sparse', these values that could be used measure the intensity of the weather. This will require explicitly defining the `SightingCategory` model with `intensity` as an attribute, and creating a new migration to add the `intensity` column to the `sighting_categories` table.

Luckily, eager loading on retrieve sighting routes will already return any values in junction tables. We will need to update any forms where we select categories and components where we display categories to enable intensity selection and display.

React Select will not allow us to input metadata for each selected element. However, we can use JSX logic to render a numeric input field to capture intensity for each selected category in our form.

## Submission

Submit pull requests to the `main` branches of Rocket's Bigfoot Frontend and Bigfoot SQL Backend repos respectively, and share your PR links in your sections Slack channel.

## Reference Solution

Here is reference code for the [frontend](https://github.com/rocketacademy/bigfoot-frontend-3.2/tree/solution-m-m-base) and the [backend](https://github.com/rocketacademy/bigfoot-sql-backend-bootcamp/tree/solution-sql-m-m-base) for this exercise, and here is a [reference deployment](https://bigfoot-solution-deployment.netlify.app/). You can do better!

### Deployment

You can also attempt to deploy your application, please follow [these instructions](https://bc.rocketacademy.co/3-backend/3.5-application-deployment).


# 3.E.5: Carousell Schema Design

## Learning Objectives

1. Know how to translate app requirements to an ERD
2. Know how to design SQL database schema for 2-sided marketplace like Carousell

## Introduction

We will create a database ERD for Carousell, a 2-sided buyer and seller marketplace. We will still only use 1-M and M-M relationships, but we will see different ways to associate tables with a different use case.

## Setup

### DrawSQL

If you haven't already, create a [DrawSQL](https://drawsql.app/) account and create a new diagram for this exercise. Choose PostgreSQL when asked to choose Database Type.

### Review Postgres data types

Sequelize data types are not always the same as Postgres data types. For example, the Sequelize `STRING` data type maps to `VARCHAR` in PostgreSQL (and DrawSQL). Review [Sequelize Data Types docs](https://sequelize.org/docs/v6/core-concepts/model-basics/#data-types) for what Postgres data types each Sequelize data type maps to.

## Base: Users Buy and Sell Products with Listings

### Define minimum necessary functionality

Always start by designing a schema for the minimum necessary functionality. In this case, we want sellers to be able to list products and buyers to be able to buy products. For now, we will assume payment takes place offline.

### Consider how to minimise duplicate data

Naively we could have separate tables for buyers and sellers, but if we look closely much of their information will be the same, for example contact information. It is also a common pattern on Carousell for users to be both buyers and sellers, and if we keep all buyer and seller data in separate tables, we would duplicate data for users that are both buyers and sellers. Duplicating data is strongly discouraged in SQL schema design.

To keep things simple, create a single `Users` table to represent both buyers and sellers. Users should have first name, last name, phone number, email and password (to store an encrypted copy of their password, not plain text) in addition to the default `id` column. All references to user IDs of buyers or sellers will reference the `Users` table.

### Create `Listings`

Next, create a `Listings` table to enable sellers to create listings and buyers to purchase listings. The `Listings` table should contain information about the product being sold such as category, title, condition, price, description, and any other relevant information such as shipping details. `Listings` should contain 2 foreign keys to the `Users` table, where the foreign keys can be named `buyerId` and `sellerId` respectively.

Add relevant relationship lines between `Users` and `Listings`. Each user can have many listings as a buyer and as a seller, hence there should be 2 relationship lines between `Users` and `Listings`. Each listing can only have 1 buyer and 1 seller. For now we assume sellers can only list 1 stock item in each listing.

### Create `Categories` and `Conditions` tables for cleaner data

Having categories and conditions data as string columns can yield messy data, because sellers can input different strings that represent the same categories or conditions. This is fine for a simple solution, but a more robust solution to support cleaner category and condition data would have separate tables for categories and conditions, and only allow sellers to choose from a fixed list of categories and conditions for each listing. There would be 1-M relationships between `Categories` and `Listings` and between `Conditions` and `Listings`.

Implement `Categories` and `Conditions` tables with associations to `Listings` to support cleaner data. `Categories` and `Conditions` only need a single `name` column other than the default `id` column.

### Good job!

If we were to create Carousell, we would now have more confidence in creating our models and migrations. At this stage in app development, there is no need to have 100% clarity on the non-relationship columns in our tables because we can always add them later, and chances are they will change as we develop and use our app.

## Comfortable: Add photos to listings

Every listing can have 1 or more photos. Create a `Photos` table that stores photos for each listing, where each row (photo) has a link to the photo and index of the photo (to represent photo order on the listing, 1st photo is cover image). Each photo should also have a `listingId` foreign key that references a row (listing) in the `Listings` table.

We store links to photos and not full files in SQL databases because files can slow our databases down unnecessarily. Instead we use file hosting services like Firebase Storage and Amazon S3 and store links to our images in SQL.

## More Comfortable: Carousell Groups

[Carousell Groups](https://support.carousell.com/hc/en-us/articles/115006419168-What-are-Carousell-Groups-) are like Facebook Groups but for Carousell. Create a `Groups` table that stores group name. Create tables to represent a M-M relationship between `Groups` and `Users`, such that users can have many groups and vice versa. Every group can have 1 or more group admin, where admin status can be represented as a column in the junction table between users and groups.

## Submission

Export your completed ERD as an image in File > Export in DrawSQL and share it in your section Slack channel.

## Reference Solution

Here is a [reference solution](https://drawsql.app/rocket-academy/diagrams/carousell) for the Base exercise. You can do better!


# 3.E.6: Carousell Auth

## Learning Objectives

1. Know how to implement industry-standard authentication in an app with a SQL backend

## Introduction

We will implement authentication in a simple Carousell clone that allows users to login, view, list and buy items. Users can browse items without logging in, but will need to login to list or buy items.

## Setup

### Fork and clone repos

Fork and clone Rocket Academy's [Carousell Frontend ](https://github.com/rocketacademy/carousell-frontend-3.2)and [Carousell Backend](https://github.com/rocketacademy/carousell-backend-bootcamp) repos.

Rocket has set up starter code such that users can:

1. View listings from the home page
2. List new items by clicking on "Sell" from the home page
3. Buy items by clicking "Buy" at the bottom of item-specific pages

The starter code follows the structure of our Bigfoot frontend and backend. Rocket followed backend setup instructions in Bigfoot SQL to set up the backend.

### Setup frontend

Run `npm i` to install packages

### Setup backend

1. Run `npm i` to install packages
2. Create and update a .env to pass crendials to  `config/database.js` Model the sample that is part of the repo, feel free to remove the sample when finished.
3. Run `npx sequelize db:create` to create the `carousell_development` database
4. Run `npx sequelize db:migrate` to set up database schema
5. Run `npx sequelize db:seed:all` to seed users and listings in the database
6. Verify seed data was added by viewing the `users` and `listings` tables in our SQL client

### Verify starter code is working

1. Start the backend with `npm start`
2. Start the frontend with `npm run dev`, and then open a browser of your choice and navigate to "<http://localhost:5173>".
3. Verify we do not get errors in our backend or frontend, and we can see 3 seed listings at "<http://localhost:5173>" in our browser. Click on a listing to view its details. Buy and sell listings to observe what happens, and notice that the buyer and seller IDs have been hard-coded to 1 (the seed user).

## Base: Require authentication to create listings and buy items

We will now put the theory we learnt in Rocket's Authentication submodule into practice.

### Setup backend API authorisation

Refer to the following official Auth0 Express Authorization guide as a reference.

{% embed url="<https://auth0.com/docs/quickstart/backend/nodejs/01-authorization>" %}
Official Auth0 route-authorisation guide for Express apps
{% endembed %}

#### Setup Auth0 API in Auth0 dashboard

1. Navigate to the API section of the Auth0 dashboard (under Applications in the left navbar) and click Create API
2. Choose a name and identifier for our API. Rocket named ours Carousell API and used `https://carousell/api` as our identifier. Leave the signing algorithm as RS256.
3. After creating the API we should see a Quick Start page. Ignore sample code on that page because it uses outdated libraries. We will be following setup instructions in the official Auth0 guide instead, which uses a [new library that replaced the outdated libraries](https://auth0.com/blog/introducing-oauth2-express-sdk-protecting-api-with-jwt/).
4. Back in the official Auth0 guide, skip the section on defining permissions for now. By default all authenticated users will be able to list and buy items in our app.

#### Install Auth0 library in our backend and use Auth0 middleware to verify authentication on protected routes

1. Install `express-oauth2-jwt-bearer`, Auth0's new, simplified library for verifying authentication
2. Import the `auth` property of `express-oauth2-jwt-bearer` in our app like in the code example in the Auth0 guide. Note that Rocket's app setup requires `import` syntax instead of `require` syntax. Copy the `checkJwt` variable definition and replace `YOUR_API_IDENTIFIER` with the API identifier we chose above.
3. Add `checkJwt` as a middleware between the route path and route handler function for our create-new-listing and buy-listing routes. See sample code under Protect API Endpoints section of Auth0 guide for reference. `checkJwt` will validate authentication before Express runs our route handler functions.
4. No need to check scopes because we are not using scopes for now.

Testing the security of our API independently is [more work than it's worth right now](https://auth0.com/docs/quickstart/backend/nodejs/02-using#obtaining-an-access-token), so we will move on and test our API together with our frontend!

### Login from frontend

We will follow the following official Auth0 guide for React apps.

{% embed url="<https://auth0.com/docs/quickstart/spa/react/01-login>" %}
Official Auth0 setup guide for React apps
{% endembed %}

#### Setup Auth0 application in Auth0 dashboard

1. Create a new Auth0 application in the Auth0 dashboard. Give it the name "Carousell" and choose the Single Page Web Application application type.
2. Add `http://localhost:5173` to Allowed Callback URLs, Allowed Logout URLs and Allowed Web Origins in the new application's Application Settings page. Save changes at bottom of page. If we deploy our app later, we will also need to add the deployed URL to these sections.

#### Install Auth0 React library and configure Auth0 resources to be available in our app

1. Install Auth0 React SDK with `npm i @auth0/auth0-react`
2. Configure the `Auth0Provider` higher-order component that wraps all other components in `index.js`. If we are logged in when viewing the Auth0 guide, we can choose the relevant Auth0 Application and Auth0 will auto-populate the properties we need for `Auth0Provider` in the guide for us to copy.

#### Retrieve Auth0 resources from React context and use them to login in our app

We want our users to be able to view all listings and individual listings without logging in. We only want them to login when they have to, in our case when they wish to list or buy items.&#x20;

We will use Auth0's `loginWithRedirect` function in 2 places: when unauthenticated users click "Sell" to list items and when unauthenticated users click "Buy" to buy items.

1. Add a `useEffect` hook in `NewListingForm` component that calls `loginWithRedirect` if the current user is not authenticated. We can check authentication status with `isAuthenticated` boolean property returned by `useAuth0` hook
   1. Retrieve the logged-in user's email with the `user` object property returned by `useAuth0` hook and send that email as the seller's email to our backend in `handleSubmit` with the other listing data.
   2. Update the relevant method within the controller attached to the  routing middleware in our backend to find or create the seller user in our backend before creating a new listing associated with that seller. Use the seller's email to retrieve their user ID in our backend. You may find Sequelize's [`findOrCreate`](https://sequelize.org/docs/v6/core-concepts/model-querying-finders/#findorcreate) class method helpful for finding a user with a given email, or creating a new user if no user exists with that email.
2. Add logic in `handleClick` in the `Listing` component to `loginWithRedirect` a user if they are not yet authenticated. This will allow users to view items without authentication, but force them to authenticate before buying an item.
   1. Retrieve the logged-in user's email with the `user` object property returned by `useAuth0` hook and send that email as the buyer's email to our backend in `handleClick`.
   2. Update the relevant route controller in our backend listingController to find or create the buyer user in our backend before updating the listing with the specified buyer's ID. Use the buyer's email to retrieve their user ID in our backend. You may find Sequelize's [`findOrCreate`](https://sequelize.org/docs/v6/core-concepts/model-querying-finders/#findorcreate) class method helpful.

Even though our users have logged in before selling or buying, our API server will still return 401 errors on sell or buy requests because we have not yet updated our requests to include auth information.

We are now ready to update our "sell" and "buy" API calls to include our auth tokens!

### Send auth tokens from frontend

We will follow the following official Auth0 API-calling guide for React apps.

{% embed url="<https://auth0.com/docs/quickstart/spa/react/02-calling-an-api>" %}
Official Auth0 API-calling guide for React apps
{% endembed %}

#### Setup frontend to retrieve auth tokens

1. Add `audience` and `scope` props to `Auth0Provider` Component in `index.jsx` in our frontend. The `audience` value should be the API identifier that we used to initialise `checkJwt` in our backend above. This may be different from the `audience` value in the Auth0 docs, because the Auth0 docs reference the Auth0 management API, not our custom API for this app.

#### Update sell and buy functionality on frontend to retrieve and send access token with API requests

1. Retrieve `getAccessTokenSilently` function from `useAuth0` hook in `NewListingForm` and `Listing` components to send the access token in sell and buy API requests respectively
2. In `NewListingForm` component, in the `handleSubmit` function that runs on form submit, call `getAccessTokenSilently` to retrieve the access token, before passing the access token in a request header to the API call with Axios. See [this tutorial](https://masteringjs.io/tutorials/axios/post-headers) and Axios docs on request method [aliases](https://axios-http.com/docs/api_intro) and [configs](https://axios-http.com/docs/req_config) for how to set request headers in Axios requests.
   1. The `audience` parameter value should be the API identifier that we used to initialise `checkJwt` in our backend above.
   2. We will need to pass the access token as an Authorization header whose value starts with "Bearer ", followed by the access token. Sample code below.
3. Do the same on `handleClick` for buy functionality in the `Listing` component. When the user clicks "buy", we should get the access token and send it with the API request to buy the listing.

Sample code from Rocket's `handleSubmit` function in `NewListingForm` component.

{% code title="NewListingForm.jsx" %}

```javascript
// Retrieve access token
const accessToken = await getAccessTokenSilently({
  // TODO: Replace with your own app's audience. Should be same as API identifier in above steps.
  audience: "https://carousell/api",
});

// Send request to create new listing in backend
const response = await axios.post(
  `${BACKEND_URL}/listings`,
  {
    title,
    category,
    condition,
    price,
    description,
    shippingDetails,
    // User is currently logged-in user
    sellerEmail: user.email,
  },
  {
    headers: {
      Authorization: `Bearer ${accessToken}`,
    },
  }
);
```

{% endcode %}

#### Verify backend can authenticate with access tokens

1. Run backend and frontend servers locally
2. List a new item on our frontend and verify that the listing gets created with the seller ID of the current user
3. Buy the newly-created listing on our frontend and verify that the listing now shows the buyer ID of the current user

Congratulations! We now have an app that allows us to buy and sell items with authenticated users!

## Submission

Submit pull requests to the `main` branches of Rocket's Carousell Frontend and Carousell Backend repos respectively, and share your PR links in your section Slack channel.

If you would like to deploy, follow deployment instructions in Bigfoot SQL M-M.

## Reference Solution

Here is reference code for the [frontend](https://github.com/rocketacademy/carousell-frontend-3.2/tree/solution-auth-base) and the [backend](https://github.com/rocketacademy/carousell-backend-bootcamp/pull/1/files) for this exercise. You can do better!


# 3.P: Full-Stack App (Express)

## Introduction

Build an Full-Stack Application in a group of 2 or 3 that solves a problem you have using React and Express. Feel free to also use any 3rd-party libraries, Firebase features, or other technologies. In this project we expect that you are developing a React Frontend Application that interacts with an Express Backend Server connected to a Sequelize Database.&#x20;

## Requirements

### App Stack

This project must be a Frontend React Application that communicates with an Express Backend Server that is able to interface with a Sequelize Database to persist information. Both the Frontend and Backend should be protected from malicious behaviour by leveraging Auth0 or JWT.&#x20;

### User Interface

* [ ] The user interface of the Frontend Application is consistently styled across all components and screens
* [ ] The Frontend Application is accessible on various devices and screen sizes
* [ ] The Frontend Application is intuitive, usable and easy to navigate
* [ ] Frontend Application has been styled with superb custom CSS, [React Bootstrap](https://react-bootstrap.github.io/components/alerts), [MUI](https://mui.com/core/) or another component UI or CSS framework

### Functionality&#x20;

* [ ] The core functionalities of the Application work as intended and expected

**Frontend**

* [ ] The Frontend Application handles props effectively across components
* [ ] The Frontend Application manages and updates state effectively
* [ ] Interactivity:
  * [ ] The Frontend Application contains at least 1 input that captures user input to alter application state&#x20;
  * [ ] The Front Application contains at least 1 call to action that alters applications state
  * [ ] The Frontend Application can reflected updated state in the UI
* [ ] Complexity:
  * [ ] Frontend Application has at least 2 levels of components eg: \
    App component and 1 or more child components
* [ ] Frontend Application must contain multiple pages this can be implemented with React Router
* [ ] The Frontend Application is required to protect components from users who are not authenticated using Auth0 or JWT

**Backend**

* [ ] Backend Application must be able to process GET, POST, PUT and DELETE requests
* [ ] Backend Application is required to persist data in PostgreSQL
* [ ] Backend Application must use Sequelize ORM to facilitate interface between Express API Server and PostgreSQL
* [ ] The Database must contain at least 1 One-Many relationship
* [ ] The Database must contain at least 1 Many-Many relationship
* [ ] The Database must utilise Sequelize Migrations to generate tables
* [ ] The Database must leverage Sequelize Seeder files populate data&#x20;
* [ ] The Backend Application should protect any sensitive routes leveraging Auth0 or JWT

### Code Quality

* [ ] Application is organised as well as structured, it follows practices of component separation and has a good folder structure
* [ ] The code is easy to comprehend and read
* [ ] The application contains meaningful variable and function names
* [ ] Application contains components that can be reused
* [ ] The application preforms well without unwarranted rendering
* [ ] The application's code follows consistent coding conventions, regarding indentations and formatting
* [ ] The application follows the correct naming, casing and commenting [best practices](/general-reference/naming-casing-and-commenting-conventions)

### Project Management

* [ ] Frontend Application has been deployed using a provider of your choice (Github Pages, Firebase Hosting, [Netlify](https://www.netlify.com/))
* [ ] Backend Application deployed using [fly.io](https://fly.io/docs/)
* [ ] Git repository contains commits for each feature with descriptive commit messages
* [ ] Application contains a README with the applications description, user stories, ERD (Entity Relationship Diagram) and wireframes
* [ ] The README contains instructions on how to run the application&#x20;
* [ ] Every group member must contribute at least 1 feature into the application
* [ ] The group worked as a cohesive team to complete the project
* [ ] Participants of the project should have updated collaboration documents and trackers&#x20;

## Ideas

As always, try to solve a problem you have. Now that we know SQL, what ideas require stricter data integrity that SQL would be helpful for? Our ideas need not be novel; they primarily need to demonstrate our ability to code well.

Ideas from past Rocket exercises: Meal tracker, workout tracker, reservation tracker, travel planner, art catalogue, bug reporting dashboard, reading list, car rental platform.

## Timeline

| Project Day | Checkpoint                                                                                                                                                                                                                 | Feedback                                                                                                                  |
| :---------: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
|      0      | <p><strong>Ideation phase 1</strong></p><p>Post project ideas in Slack for feedback</p>                                                                                                                                    | SL to review ideas and share feedback                                                                                     |
|      1      | <p><strong>Ideation phase 2</strong><br>Create planning docs: user stories, wireframes, kanban board</p>                                                                                                                   | SL to review planning docs and share feedback                                                                             |
|      2      | **Start implementation**                                                                                                                                                                                                   | -                                                                                                                         |
|      3      | -                                                                                                                                                                                                                          | -                                                                                                                         |
|      4      | -                                                                                                                                                                                                                          | -                                                                                                                         |
|      5      | <p><strong>MVP deadline</strong><br>Users can complete the primary user story</p>                                                                                                                                          | SL to review code in GitHub, share feedback                                                                               |
|      6      | -                                                                                                                                                                                                                          | -                                                                                                                         |
|      7      | <p><strong>Feature freeze</strong></p><p>No new features, focus on polishing existing features and code to be presentable</p>                                                                                              | SL to review progress and share post-feature-freeze suggestions                                                           |
|      8      | -                                                                                                                                                                                                                          | -                                                                                                                         |
|      9      | <p><strong>Project presentations</strong></p><p>Practise <a href="/pages/vnQ0MkMbmPv2pn2pzRko#presentations">explaining your work</a> to others. Other batches will join and we will celebrate each others' hard work.</p> | SL to review code in GitHub, share feedback in 30-minute [post-mortem meeting](/logistics/course-methodology#post-mortem) |
|      10     | <p><strong>Demo video</strong><br>Record a <a href="/pages/vnQ0MkMbmPv2pn2pzRko#demo-video">demo video</a> for employers and the public, embed in README</p>                                                               |                                                                                                                           |

## Setup

Start by forking Rocket's Bootcamp Project 3 [frontend](https://github.com/rocketacademy/project3-3.2) and [backend](https://github.com/rocketacademy/project3-backend-bootcamp) repos that contain an empty CRA app and an empty Express app respectively. This will make it easier for SLs to review your code via pull requests.

To set up Sequelize in your backend repo, you may find Rocket's Sequelize Setup instructions helpful from Module 3's Bigfoot SQL exercise.

To enable frontend and backend servers to communicate with each other, you may wish to set up CORS middleware in our Express app as described in the Express.js submodule.

## Deployment

Rocket recommends deploying our frontend to either [Netlify](https://create-react-app.dev/docs/deployment/#netlify) or [Firebase Hosting](https://create-react-app.dev/docs/deployment/#firebase) because they allow for client-side routing by React Router, unlike GitHub Pages.

Rocket recommends deploying our backend to [Fly.io](https://fly.io/) because Fly provides an easy way to deploy servers to the cloud and connect with a managed PostgreSQL instance.&#x20;

See Bigfoot SQL M-M exercise for detailed deployment instructions for Netlify and Fly.io.

## Submission

1. Submit a pull request to Rocket's Project 3 repo
2. Add your Project 3 repo link to the Rocket Bootcamp Projects spreadsheet in your batch-specific sheet shared by your SL


# 4: Capstone

We've learned the foundational components of software systems and how to build full-stack web applications. In this module we'll briefly explore advanced topics that will further bolster your career as a software engineer.


# 4.1: Testing

## Learning Objectives

1. Programmatic software testing is a crucial feature of software development that all tech companies practice
2. Programmatic testing allows us to quickly verify we did not break existing features when building new ones
3. Programmatic testing involves writing code to test our code
4. There are 3 general categories of programmatic tests: unit tests, integration tests and end-to-end tests

## Introduction

Every mature software product has software tests to verify intended functionality. Without software tests, every time we write a new feature we might not know whether we broke an existing one. This lack of clarity can cause stress, especially when existing features are crucial to user experiences. Engineers working on early-stage products often omit writing tests because their product requirements change often, but once product requirements start to stabilise and mature, testing is necessary to maintain engineer sanity.

Software tests are code written using 1 or more test frameworks that programatically verify that functions, groups of functions, or entire features produce expected output when provided with specific input. Engineers typically merge these tests to repos at the same time they merge the tested feature, guaranteeing tests for every feature in the product. Some engineers prefer to write tests before writing the feature (aka test-driven development), and others prefer to write tests after or while writing the feature (more common).

There are 3 most common categories of software tests: unit tests, integration tests and end-to-end tests. Unit tests typically test individual functions, especially ones with non-trivial logic such as calculations. Integration tests typically test groups of functions, for example a function that triggers functionality in multiple helper functions. End-to-end tests typically test entire features by using frameworks to simulate user actions, and verifying that those actions cause the desired database and UI changes in the app. Unit tests are the simplest and most common form of testing, and engineers often omit end-to-end testing until their product matures.

There is no such thing as perfect testing, but hopefully with mindful testing we can eliminate bugs that would otherwise have happened unnoticed without tests.

## Unit Testing in JavaScript

### Introduction

For illustration purposes we will demonstrate unit testing in JavaScript. For Bootcamp projects and take-home interview assignments, it should be sufficient to write unit tests on our functions like this one.

[Mocha](https://mochajs.org/) and [Chai](https://www.chaijs.com/) are common test frameworks used together to test JavaScript backends. Mocha is the framework that enables us to run tests. It provides functions in which we can write tests, and a test runner script we can use to run all of a subset of our tests. Chai is an "assertion framework" that allows us to verify values in our code match what we expect, values such as the return value of the function we are testing. Jest is a more common test framework used for frontends that has the same functionality as Mocha and Chai combined.

### Setup

Fork and clone Rocket's [`unit-test-bootcamp` repo](https://github.com/rocketacademy/unit-test-bootcamp) to follow along. We have implemented a simple unit test example using Rocket's Express app template.

Before we wrote tests, we created a module to test. In this case, we have created a basic `utils` module in `utils.js` that exports an `add` function that adds 2 numbers. Trivial, but you can imagine more complex functions such as those we implemented for games like Blackjack.

{% code title="utils.js" %}

```javascript
const add = (a, b) => {
  return a + b;
};

module.exports = {
  add,
};
```

{% endcode %}

Next we set up our test framework.

1. We installed Mocha and Chai libraries as development dependencies. Development dependencies are only used during development and do not need to be included in the final app package shipped to users, helping make the app package smaller.

   ```
   npm i --save-dev mocha chai
   ```

2. We added a script in `package.json` that allows us to run tests by running `npm test`.&#x20;

   ```
   "test": "mocha"
   ```

3. We added the Mocha env setting to `.eslintrc.js` for ESLint to support Mocha syntax.

   ```
   mocha: true,
   ```

4. We created a folder `test` in the root of the repo to store our test files. By default Mocha looks for a folder called `test` to find tests.

   ```
   mkdir test
   ```

At this point we created our test file and wrote our tests in it. We will dissect the test code below.

{% code title="test/utils.js" %}

```javascript
const { expect } = require("chai");
const { add } = require("../utils.js");

describe("Utils", () => {
  describe("Add", () => {
    it("Adds 2 of the same number", () => {
      const result = add(1, 1);
      expect(result).to.equal(2);
    });

    it("Adds 2 different numbers", () => {
      const result = add(1, 2);
      expect(result).to.equal(3);
    });

    it("Adds a positive and a negative number", () => {
      const result = add(1, -1);
      expect(result).to.equal(0);
    });

    it("Adds 2 negative numbers", () => {
      const result = add(-1, -1);
      expect(result).to.equal(-2);
    });
  });
});
```

{% endcode %}

Now if we run `npm test` from our repo in the command line we should get the following output.

```
unit-test-bootcamp % npm test

> unit-test-bootcamp@1.0.0 test
> mocha

  Utils
    Add
      ✔ Adds 2 of the same number
      ✔ Adds 2 different numbers
      ✔ Adds a positive and a negative number
      ✔ Adds 2 negative numbers

  4 passing (4ms)

unit-test-bootcamp % 
```

### Syntax

#### `expect`

At the top of our test file `test/utils.js` we imported the `expect` module from Chai. `expect` is an "assertion" syntax that helps us "assert" that our code meets expectations.

Observe in each of the `it` blocks (we explain `it` below) how we use `expect` to verify expected values using a pseudo-English syntax.

[Chai's API reference](https://www.chaijs.com/api/bdd/) provides a list of assertions we can perform with `expect`.

#### `describe`

`describe` is a syntax for grouping and categorising tests. Notice each `describe` block accepts a string followed by a function, where the string is the description of the group of tests contained within the function.&#x20;

We can nest `describe` blocks within each other to group different types of tests. For example, each function that we test can be in its own nested `describe` block. In our case, our `add` function has its own nested `describe` block, and we could add another nested `describe` block for `subtract` function tests if we ever added a `subtract` function to `utils`.

Notice Mocha logs the description for each `describe` block in the console when running tests.

#### `it`

`it` declares an individual test. Like `describe`, `it` accepts a string followed by a function, where the string is the test description and the function is the test logic. Mocha engineers chose `it` as the function name so that test descriptions could read more like plain English, e.g. `it("Adds 2 of the same number", () => { ... });`

If you put an x infront of any it or describe your test will be skipped.

## Exercises

1. Run the tests in Rocket's repo and review output
2. Break a test on purpose to see what a failing test looks like, e.g. by changing the expected result
3. Add a `multiply` function to `utils` and write tests for it

### React and ExpressJS testing

If you would like to explore testing in your React frontend or ExpressJs backend please read sections [4.1.1](/4-capstone/4.1-testing/4.1.1-frontend-react-testing) and [4.1.2](/4-capstone/4.1-testing/4.1.2-backend-expressjs-testing).&#x20;


# 4.1.1: Frontend React Testing

## Learning Objectives

1. Understand that we can test React Components on our Frontend Application
2. Gain some insight in how to use React Testing Library to test our code
3. Implement programatic tests on a React Component&#x20;

## Introduction

React Testing Library is the suggested testing library for testing React Applications and Components. It contains a set of utilities and API's that enable developers to write tests which simulate user behaviour and interaction with their React Components. Developers can then assert and check if the expected behaviour is executed.&#x20;

Lets try to develop a high-level understanding of how React Testing Library operates:

1. Rendering the Component:
   1. Firstly we will need to render the Component that we want to test using React Testing Library's `render()` method. The `render()` method creates a virtual dom and mounts the component in memory, it will then return the object that contains references to the rendered element.&#x20;
2. Finding Elements:
   1. After you have rendered the component you are able to use the `getBy*()` or `queryBy*()` methods that can be extracted from the React Testing Library. These methods help developers to find specific elements rendered on the Component, they search for Component elements by targeting attributes such as text content or other characteristics.&#x20;
3. Simulate User Interactions:
   1. Once you have successfully selected your elements that your user will interact with you are able to simulate user interactions by calling the `fireEvent()` method, which comes from React Testing Library. We are able to trigger all types of events such as clicks, form submissions and key presses.
4. Assert Results:
   1. To actually check if your components are working in the correct manner, we are able to utilise the `expect()` function from Vitest in this case. With this function we can make assertions concerning the behaviour of the tested Component. We are able to check if the specific element is present, if an event has occurred or if a components state has been updated.

We are able to leverage React Testing Library such that we can test out Components as a user would interact with our application.&#x20;

### Setup

Fork and clone Rocket's [testing-react repo](https://github.com/rocketacademy/react_testing_2024)  to follow along. We have implemented some simple tests within a React environment. Once you have cloned the repository onto your local machine install all of the dependencies with the command

```
npm install
```

Following this you will be able to run React tests by running the command below within the root of the project directory.

```
npm test
```

## Testing React Components

React applications created with the create-react-app contain a basic test that validates the boiler plate code that is provided, it just ensure that the App component loads an contains some text, learn react. We have left this test inside Rocket's testing-react repo.

When developing Frontend applications it is useful to test your component to ensure that your application is rendering the appropriate components, to test if data API's are called onload, or event to check if buttons are firing off the correct functions. To do all of this we can use React Testing Library, it provides a set of utilities that enable developers to test React Components. With this library we are able to simulate how users interact with the application meaning, we are able to write tests that follow user behaviour. These tests ensure that our Components are working as expected within our application.

Here's an example of how to test a button click and the actions that occur after:

{% code title="Button.test.js" lineNumbers="true" %}

```javascript
import { describe, expect, test } from "vitest";
import { screen, render, fireEvent } from "@testing-library/react";
import Button from "../Components/Button";

describe("Button", async () => {
  test("should call onClick when clicked", async () => {
    render(<Button />);

    const button = screen.getByText("Click me");

    expect(screen.getByText("Please click")).toBeInTheDocument();

    await fireEvent.click(button);

    expect(screen.queryByText("Please click above")).not.toBeInTheDocument();

    expect(screen.getByText("Clicked = 1")).toBeInTheDocument();
  });
});
```

{% endcode %}

In the example above we are testing the `Button` Component that has an `onClick` property. The test makes use of the `render` method from React Testing Library, it is used to render the Component. We then select the button with the `getByText` utility function. We are able to check if the correct text is showing on load, by checking if "Please click above" is being rendered. We then use the `fireEvent.click()` method from React Testing Library to simulate a clickEvent, on our rendered Component. This allows us to check the outcome of the click event, in this case, the removal of the string 'Please click above' that is replaced with "Clicked = 1" which is the current count.

It should be noted that if your `Button` Component triggers an action after the click, like calling an API, we are able to apply additional assertions to test that the additional triggers were fired off as expected. You can see how we can achieve this below. &#x20;

{% code title="ButtonComplex.test.js" lineNumbers="true" %}

```javascript
import { describe, expect, test, vi } from "vitest";
import { render, fireEvent, screen } from "@testing-library/react";
import Button from "../Components/ComplexButton";
import axios from "axios";

vi.mock("axios");

describe("Button", () => {

  test("should call onClick and fetch data when clicked", async () => {
  
    render(<Button />);
    
    const button = screen.getByText("Click me");
    
    fireEvent.click(button);
    
    expect(axios.get).toHaveBeenCalledTimes(1);
    
    expect(axios.get).toBeCalledWith(
      "https://pokeapi.co/api/v2/pokemon/geodude"
    );
  });
});
```

{% endcode %}

In the above example we are testing if `Button` Component fire's off an API call. To test if our code is actually calling an API we have to import the `axios` library and mock it using the `vi.mock()` function. Next we render out our `Button` Component, we use the `getByText` method to find the `Button` so that we can fire off a click event, using `fireEvent.click()`. We can then assert that the mocked `axios.get()` has been called  using Jest's `toHaveBeenCalledTimes` moreover we can test that it has been invoked along with its expected argument.&#x20;

When we want to test if an API has been called following a click event witin React Testing Library, we will need to mock the API library, in the case above `axios`. We can then assert that the method has been called with the correct arguments and is actually invoked. This approach means that you can test the functionality of the component without making the API call during tests.&#x20;

### Additional Help

If you would like to explore React Testing Library some more, checkout [this video series](https://www.youtube.com/watch?v=7dTTFW7yACQ)!


# 4.1.2: Backend Expressjs Testing

## Learning Objectives

1. Understand how to test Expressjs applications using supertest to preform end to end testing
2. Understand how to test Expressjs controller functions using mocha and chai to ensure they are calling the correct database methods and responding correctly.&#x20;

## Setup

To showcase how to use Supertest as well as unit testing we will be utilising the ExpressJS Fruit Backend, auth0 is implemented to protect certain routes and we are getting data from a Sequelize database. Fork and clone Rocket's [testing-express repo](https://github.com/rocketacademy/testing_expressjs), please follow this setup to test out the repository. Inside this repository we have installed the required packages to run and test the application. The new testing libraries that we added include `supertest`, `mocha`, `chai`, `sinnon` and `sinnon-chai.` We use `supertest` and `chai` to preform tests on the Server. While we use `mocha`, `chai`, `sinon` and `sinon-chai` to test the Server controller methods.&#x20;

Once you have cloned the repository onto your local machine install all of the dependencies with the command, run the command in the root of the project directory

```
npm install
```

<mark style="color:red;">**You will then need to alter the sample.env and add in your own credentials.**</mark>&#x20;

After you have installed the relevant packages you will need to run some commands to develop a test database that your application will get information from. The test database will need to have a name that is not the same as any database currently running within your Postgres server. Run these commands in the root of the project directory

```
npx sequelize db:create
npx sequelize db:migrate
npx sequelize db:seed:all
```

Following this you will be able to run React tests by running the command below within the root of the project directory.

```
npm test
```

## Supertest

### Introduction

Supertest is a brilliant library that allows developers to test Node.js HTTP server as well as ExpressJs applications. I contains a simple and easy to use API for testing HTTP requests on your server, along with great assertions to ensure that responses are correct. Supertest is used with common testing libraries like Jest or Chai to supply assertions. &#x20;

Lets look Supertest from a high-level overview:

1. Create the request object:
   1. In order to make requests to your server through Supertest, we will first need to create a request object by utilising the `request()` method. As an argument method takes your ExpressJs server instance, it will then return a request object that you can then call HTTP requests on.
2. Fire off HTTP request:
   1. Once the request object has been instantiated you are able to use invoke the various HTTP methods that you already know (`get()`, `post()`, `put()`, `delete()`...). These methods will be used to make requests to your server, the arguments for these methods are a URL path and any optional data as required. &#x20;
3. Assert the expected responses:
   1. After the request has been made you can use the expect() method to check the response and assert your expected outcomes. These methods allow you to check the response in the same way a browser checks, you can check virtually any property such as the status code, headers and body.
4. Handle response errors:
   1. Supertest also allows you to handle any response errors that may occur then you make your requests. Such that you know your application is responding as expected under error conditions.&#x20;

We are able to leverage Supertest along with Chai to test out our backend applications ExpressJs route handlers to ensure the application operates as expected.&#x20;

### Understanding Supertest

Supertest's flow is explained above, lets see how its implementend in code:

{% code title="supertest.spec.js" lineNumbers="true" %}

```javascript
const supertest = require("supertest");
const chai = require("chai");
const app = require("../index.js");
const expect = chai.expect;

// Get 
describe("GET / ", async () => {
  it("should recieve status code 200", async () => {
    const response = await supertest(app).get("/");
    expect(response.headers["content-type"]).equal("text/html; charset=utf-8");
    expect(response.status).equal(200);
    expect(response.text).equal("Incorrect path");
  });
});
```

{% endcode %}

In the example able we are using `chai` as our assertion/expectation library. On line 9 we creating our request object and firing off a `get()` request to the `'/'` url path. This response is stored in a variable and we must await the Supertest request to complete. Once its completed we are able to check the values within the response using our assertions from chai.&#x20;

Checkout the example repository and see if you can apply this to your own code. If you would like to learn more about Supertest, checkout their [documentation](https://www.npmjs.com/package/supertest).&#x20;

## Unit Testing

### Introduction

When testing your application you want to have as much test coverage as possible. While Supertest will test your controller functions by responding with the correct information from your linked database, you may want to ensure that your controller methods are always preforming as expected. You can do this by developing unit tests where by we mock the environment, request, response as well as database methods using Mocha and Chai. To test your backend controller mehtods you can follow these steps.

1. Setup a test database:
   1. Before you run the tests it is important that you setup a test database such that your controller functions can access a operational database in the repository that we have supplied we are using sequelize as a database querier. This means we need to import the require model into the test while mocking the seqeulize package and methods.
2. Decide on which controller functions to test:
   1. You should test the controller functions within your ExpressJs application that accesses your database to retrieve some information.
3. Setup the files environment:
   1. We will use sinon to develop a sandbox environment for our tests. Then we will setup the controller within our beforeEach block. After which we define the information we will use to mock our database, the request objet as well as the response object. In the afterEach block we restore sinon and the sandbox.
4. Writing test cases:
   1. For each test we need to create stubs that resolve data, we create stubs using sinon for each sequelize method we are testing. Then you can write test cases that simulate HTTP requests that your controller functions handle, by calling the controller method. We are then able to write assertions for the expected responses.&#x20;
5. Handle Response Errors:
   1. mocha and chai also allows you to handle any response errors that may occur then you make your requests. Such that you know your application is responding as expected under error conditions.&#x20;

&#x20;

### Understanding these tests

To understand how these tests operate and function please checkout the code and explanation below.&#x20;

{% code title="fruitControllerTest.spec.jss" overflow="wrap" lineNumbers="true" %}

```javascript
// Get all imported packages and modules
const chai = require("chai");
const sinon = require("sinon");
const sinonChai = require("sinon-chai");
const sequelize = require("sequelize");
const db = require("../db/models/index");

// Set up the fruit model, setup chai assertion
const { fruit } = db;
const expect = chai.expect;

// Tell chai to use sinonChai
chai.use(sinonChai);

// Start to write our testing environment
describe("fruitController", async () => {
  describe("List function", async () => {
    
    // Set up the sandbox using sinon so that we can keep tests seperate
    const sandbox = sinon.createSandbox();
    // Set up required variables
    let sampleReturnedFruitList, req, res, FruitController, fruitController;

    // before we run the test we will run this block
    beforeEach(() => {
      // define the fruit Controller that we will be testing
      FruitController = require("../controllers/FruitController");
      fruitController = new FruitController(fruit);
      // define the sample data we will run through the controller methods
      sampleReturnedFruitList = [
        {
          id: 1,
          name: "Apple",
          description: "This apple is crisp and sweet",
          colour: "Red",
          stock: 140,
          price: 15,
        },
        {
          id: 2,
          name: "Banana",
          description: "This banana is yellow and sweet",
          colour: "Yellow",
          stock: 200,
          price: 12,
        },
      ];
      // develop a mock request
      req = {};
      // develop a moct response
      mockResponse = () => {
        const res = {};
        res.status = sinon.stub().returns(res);
        res.json = sinon.stub().returns(res);
        return res;
      };
      res = mockResponse();
    });

    // This block runs after each test is run
    afterEach(() => {
      // restore all stubbed functions and the sand box
      sinon.restore();
      sandbox.restore();
    });
    
    // write out the what we are testing for
    it("Can calls the findAll method to get the data from the database", async () => {
      // Create a stub for the findAll method from sequelize, it resolves the sample data above
      let findAllStub = sandbox
        .stub(sequelize.Model, "findAll")
        .resolves(sampleReturnedFruitList);
      
      // call the controller mehtod
      await fruitController.list(req, res);
      
      // set up the assertions
      expect(findAllStub.calledOnce).to.be.true;
      expect(res.json.calledOnce).to.be.true;
      expect(res.status.calledOnce).to.be.false;
      expect(res.json).to.be.calledWith({
        fruit: sampleReturnedFruitList,
        message: "success",
      });
    });
  });
```

{% endcode %}

In the example above we have set up the testing environment and are testing the list function of the fruitController. We are checking to see if the method is being invoked, we then check is see if the sequelize interactions are being fired off, and then we can see if our code is executing correctly.

At the end of the day testing Express controller functions using Mocha and Chai will mean you need to set up a testing database, you need to have testable controller functions, write tests that simulate HTTP requests running through your server. Moreover you need to assert all responses and mock the external dependancies such that when you test your controller functions we can ensure that they are utilising the database and responding correctly.

Here are some helpful sets of documentation that should help you to extend these tests in your portfolio projects.&#x20;

mocha: <https://mochajs.org/>

chai: <https://www.chaijs.com/>

sinon: <https://sinonjs.org/>

sinon-chai: [https://www.chaijs.com/plugins/sinon-chai](https://www.chaijs.com/plugins/sinon-chai/)/

See if you can apply these types of tests into your applications. Checkout the package.json to see how we are running npm test.


# 4.2: Continuous Integration

## Learning Objectives

1. Continuous integration (aka CI) means automatically running tests when there have been any changes to our code
2. Every tech company relies on CI to verify their systems are operational
3. CI is often referred to together with "CD" or continuous deployment
4. CI is typically integrated into the development workflow, running tests on pull requests and merges

## Introduction

Continuous integration (aka CI) means automatically running tests when there have been any changes to our code, and notifying engineers when any tests fail. This helps engineers know proactively when their changes have broken existing functionality without having to manually run tests.

Every tech company relies on CI to verify their systems are operational. Testing culture varies across tech teams, and some teams will have more robust test coverage than others. Skipping writing tests may speed up development in the short term but slow down development in the longer term when new changes introduce unexpected and undetected bugs.

CI is often referred to together with CD, which stands for continuous deployment. This is because the same tools that allow us to run tests on code changes can also allow us to deploy our apps on code changes after tests pass. Because both are often used together, we often refer to them as "CI/CD".

CI is typically integrated into the development workflow, running tests on pull requests and merges. We will demonstrate how to use CI with [GitHub Actions](https://github.com/features/actions) below, but there are other popular CI alternatives such as CircleCI, Travis CI, GitLab CI and Jenkins.

## GitHub Actions

GitHub Actions are sequences of command line commands we can run automatically on specific triggers such as pull requests or pushes to specific branches. GitHub Actions allow us to run command line commands in an environment of our choice (e.g. Ubuntu, Windows, MacOS), and on triggers of our choice (e.g. on specific branches but not others). These features and their usage are similar across most CI software.

GitHub Actions (and most cloud infrastructure automation) are typically configured using [YAML](https://en.wikipedia.org/wiki/YAML), a language similar to JSON except with the option to add comments for explanations. To create a new "workflow" or sequence of commands, we create a new YAML file in a `.github/workflows` folder in the root of our repo. Once we commit a new workflow to our repo, GitHub Actions can execute it if our subsequent actions match the triggers we specified in our workflow, such as pushing to the `main` branch. GitHub has comprehensive docs on the [various options developers have to configure GitHub Actions](https://docs.github.com/en/actions) and the [specific YAML syntax for workflow files](https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions).

Rocket has created a [simple CI workflow](https://github.com/rocketacademy/unit-test-bootcamp/blob/main/.github/workflows/ci.yml) using the `unit-test-bootcamp` repo we introduced in the Testing submodule, copied below. Rocket's GitHub Actions workflow is modelled after the [GitHub Actions Node.js starter workflow template](https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs).

{% code title=".github/workflows/ci.yml" %}

```yaml
# This workflow will launch a clean Ubuntu OS, install app dependencies and run tests
name: CI

# Run on push or PR to main branch
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  build:
    # Specify which OS to run this workflow on
    runs-on: ubuntu-latest

    strategy:
      matrix:
        # Specify Node version
        node-version: [16.x]

    steps:
      - uses: actions/checkout@v3
      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v3
        with:
          node-version: ${{ matrix.node-version }}
      # npm ci is a built-in script to install dependencies from package-lock.json
      - run: npm ci
      # Run tests
      - run: npm test
```

{% endcode %}

After pushing the above workflow to `main`, we can observe this workflow in the [Actions tab](https://github.com/rocketacademy/unit-test-bootcamp/actions) in the GitHub console.

![GitHub Actions tab in GitHub console](/files/wtbCehG1BxpxyxFa4bk8)

We can inspect what happened in this workflow by clicking into it.

![GitHub shows us each stage of the GitHub Action workflow](/files/trgbg0pgkqjyqt2olArw)

For more detailed analysis of the workflow, we can click on each of the workflow stages to observe what happened in that stage. For example, we can click into the "Run npm test" stage to verify the correct tests ran.

![GitHub allows us to view exact command line output from each workflow stage](/files/coJhN8yj36hIFynwkan6)

In addition to running CI, GitHub Actions also allows us to deploy our apps automatically with continuous deployment (aka CD). Read about [GitHub Actions' Deploy to Heroku library](https://github.com/marketplace/actions/deploy-to-heroku) for a convenient way to deploy our apps to Heroku on GitHub pull requests and merges.

## Additional Resources

1. GitLab provides a [simple yet comprehensive introduction to CI/CD concepts](https://docs.gitlab.com/ee/ci/introduction/)


# 4.2.1 Continuous Deployment (Fly.io)

## Learning Objectives

1. Continuous Deployment (CD) is a software engineering approach in which our application code can be automatically released, and deployed onto our running environment whenever pushed onto `main` branch in our Github repositories
2. Understand how to setup Github actions to set up a pipeline to connect our repository directly with our deployed fly.io environment
3. How to ensure we protect our `.env` variables even when using github to automatically connect to our fly.io environment

## Introduction

Continuous Deployment, often times linked closely with Continuous Integration (CI), automatically deploys all code changes that are pushed into a specific branch in your repository, designated by you or your team, through a pre-set up pipeline.&#x20;

Just like CI, CD is utilised by almost every tech company to automatically deploy code to their testing, development or even production environments. However, CD is almost never done on its own with out having CI taking place.

Just like we did in [4.2 Continuous Integration](/4-capstone/4.2-continuous-integration), we will be utilising GitHub Actions to demonstrate how this works.

## Pre-requisites

1. **Deployed Backend**

Before setting up CD, the Backend would need to have already been deployed as laid out  [here](/3-backend/3.5-application-deployment). if not, it is recommended to have the deployment completed before carrying on.

2. **Setting up proper env variables.**

As the `fly.toml` would now need to be pushed into github, we would need to set up our `.env` variables somewhere else as we would like to prevent our keys to the Backend to be uploaded into github. To do this, first we would need to open up our terminal to the root directory of our deployed backend project.

For each of the environmental variables, the following code would need to write:

`fly secrets set <ENV NAME>=<env value>`

Each time the code is run, the instance may restart and take a bit of time before you can enter the next variables

To see all the environmental variables on the instance, run:

`fly ssh console -C "printenv"`

Now that this is set up, it is important to remember to delete the `[env]` variables from the `fly.toml` file.

## Setting up Continuous Deployment

To ensure that CD can be set up remotely (via GitHub), a token would need to be generated first. To do this, run open up your terminal to the root directory of your deployed project and run the following command:

`fly tokens create deploy -x 999999h`

Copy the generated token, and open up the GitHub repository and open up the setting tab.

In the setting tab, look for `Secrets and variables` and select `Actions` under it.&#x20;

![](/files/emydMsSSkWQOhsehU2x5)

Create a new token and name it `FLY_API_TOKEN` and save the token generated under this secret.

Back in VScode, create a new file under `.github/workflows/` called `fly.yml`

Copy and paste the following into the file

```yaml
name: Fly Deploy
on:
  push:
    branches: [main]
     
jobs:
  deploy:
    name: Deploy app
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: superfly/flyctl-actions/setup-flyctl@master
      - run: flyctl deploy --remote-only
        env:
          FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
```

Commit changes, and check out the `actions` tab to see if the app is being deployed onto Fly.io!


# 4.2.2: Circle Ci

## Learning Objectives

1. Understand what CircleCI is capable and how it can help speed up deployment and development
2. Understand how CircleCI links with a Github branch and Netlify project
3. Implement a flow where, a push to Github will lead to Netlify re deploying our application
4. Implement CircleCI for CI and CD&#x20;

## Introduction

CircleCI is a platform to implement CI (continuous integration) and can be integrated with Netlify to provide CD (continuous delivery), CircleCI provides an automated and streamlined workflow to build, test as well as deploy applications. This platform, CircleCI exists as a cloud-based service that integrates to well known version control systems such as Github and Bitbucket. CircleCI supports a plethora of languages as well as frameworks meaning many developers, companies and corporations use this tool.

Lets discuss some benefits of CircleCI:

1. Make builds and test automated:
   1. When using CircleCI you can automatically trigger builds and tests on your code repositories every time you are pushing and altering code on a Github branch. This is helpful to ensure your code is executing as expected and ensures no incomplete version that fails tests is built or deployed.&#x20;
2. Customise you workflow:
   1. You are able to develop custom workflows using CircleCi to specify the required instructions and commands to build, test as well as deploy your application. Using this tool we are able to configure environmental variables, target deployments and more.
3. Integratable:
   1. CircleCI was created with integration in mind, it has an abundance of services and tools that could be used in your workflow. This includes many cloud providers such as AWS and Netlify, testing tools like Jest, Mocha and Chai, and code formatters like ESlint.
4. Scaleable and Secure:
   1. It has parallel testing along with distributed builds intended to speed up the development cycle. Moreover CircleCI provides secure features like SSH access, environmental/ secret management as well as checking compliance certifications such as SOC 2.&#x20;
5. Analytics:
   1. This platform produces detailed insights into your applications, builds, test results and deployment, allowing developers to track performance, identify errors and improve the work flow.&#x20;

## Setup

In order to demonstrate the how useful CircleCI is a helpful tool, we will deploy a Firebase application to Netlify, we will setup a system such that when we push to GitHub CircleCI will trigger an workflow to build the latest code and update our deployed site. Please fork and clone [this repository](https://github.com/rocketacademy/circle_ci_example), you will need to supply your own Firebase credentials and Applications details, you can use the Firebase Application you created for [M2 Instagram Bootcamp](/2-full-stack/2.e-exercises/2.e.5-instagram-routes).&#x20;

You need to follow the steps below to setup the application before you can start to setup CircleCI, Netlify and our deployment workflow.

Once you have cloned the repository onto your local machine install all of the dependencies with the command, run the command in the root of the project directory

```
npm install
```

<mark style="color:red;">**Alter the sample.env**</mark>

<mark style="color:red;">**You will then need to alter the sample.env and add in your own credentials. This will require you to have a Firebase Application that has these Firebase tools, RealTimeDatabase, Storage and Auth.**</mark>&#x20;

Following this you will be able to run the React Application by running the command below within the root of the project directory.

```
npm start
```

Check to see if you're able to get the posts saved in your Firebase RealTimeDatabase. Here is a sample of how it may look, I have added some fruit images online, here you can see an apple. Your image will be whatever you added during [M2 Instagram Bootcamp](/2-full-stack/2.e-exercises/2.e.3-instagram-posts).&#x20;

<figure><img src="/files/c84f6AAi8vPItcQNoTsK" alt=""><figcaption><p>Sample CircleCI Firebase application - running on localhost</p></figcaption></figure>

If you cannot see your posts appear you may need to alter these variables within the cloned and forked application:

{% code title="Form.js / Landing.js" lineNumbers="true" %}

```javascript
const DB_MESSAGES_KEY = "messages";
const STORAGE_FILES_KEY = "images/";
```

{% endcode %}

Once you've ensured you can get your data we can continue to the next step.

## Netlify Deployment&#x20;

The cloned application already includes `netlify-cli,` but if you're applying these steps onto your own project you will need to install the package, run this command in the root of the project directory:

```
npm install --save-dev netlify-cli
```

You need to make sure your current code is on GitHub, if you've forked and cloned, then it is but if you're applying this to your application make sure its online.&#x20;

At this point we can create a new branch, we can name it, `netlify-ignored-deployment,` or whatever name you would like. Push this branch online. The naming convention of the branch may lead you to wonder why we need it. Netlify tracks a projects branch to trigger application deployment and we want to ensure that we do not run two deployment processes simultaneously. To prevent this we make Netlify track this dummy branch.&#x20;

<mark style="color:red;">**We will not be pushing changes to this branch.**</mark>

### Online Application

To deploy an application on Netlify you must goto the Netlify App online and login, click into the `Sites` tab and click on `Add new site`:

<figure><img src="/files/bsKiGM7A08aPKRGI5V2Z" alt=""><figcaption></figcaption></figure>

Click on `Import an existing project`:

<figure><img src="/files/TmoECuluHKv2OOQ5NEEb" alt="" width="356"><figcaption></figcaption></figure>

Choose GitHub as the provider:

<figure><img src="/files/Cnqd0D4ud8JZeCoS4dpX" alt="" width="563"><figcaption></figcaption></figure>

Select the project that you want Netlify to track, it should be your forked repo:

<figure><img src="/files/k0OEPbBTKjXXt81pj3bl" alt="" width="563"><figcaption></figcaption></figure>

&#x20;Now add in the branch that Netlify should track and deploy from, I am going to target `netlify-ignored-deployment:`

<figure><img src="/files/QStgt4NrdjVPdDozx31m" alt="" width="563"><figcaption></figcaption></figure>

After this you can click on the `Deploy site` option.&#x20;

This will trigger your repository to be deployed with Netlify, you should be able to see the site on a url that looks like: `sitename.netlify.app`&#x20;

At this point your application is probably erroring this is because you need to set up the Environmental variables that are in our application. To do this goto your Netlify application dashboard, select `Site settings`:&#x20;

<figure><img src="/files/aMvWPApYIDeYCodEXdcw" alt="" width="563"><figcaption></figcaption></figure>

Then click on the `Environment Variables` tab, and the `Add a variable` button, on the dropdown click on `Import from a .env file`:

<figure><img src="/files/QcRm9TMNz8POKelwrAhZ" alt="" width="563"><figcaption></figcaption></figure>

At this point copy the .env that you created to test out the React App. Once you've placed in all of your enviromental variables click on `Import variables`.

<figure><img src="/files/qo7u7NQBelkEWumMG0gH" alt="" width="563"><figcaption></figcaption></figure>

At this point click back onto the `Deploys`tab, select the current project, click on the `Trigger deploy` button, and then click on `Deploy site`. At this stage you should be able to goto your deployed website and it should replicate your version running on localhost as its accessing the same Firebase RealTimeDatabase.

&#x20;

<figure><img src="/files/ozduut5QMgWrYWTdZOHj" alt="" width="563"><figcaption></figcaption></figure>

Now that we have successfully deployed our React-Firebase Application on Netlify we will need some credentials from Netlify so that we can preform automated deployment from our CircleCI workflow. You are going to need the **`APP ID`** as well as the **`Personal Access token`** from Netlify.

Please save these values so you can access them later.&#x20;

You can retrieve the `APP ID` from your Netlify Applications dashboard, `Site settings`, `Site details`:

<figure><img src="/files/eNSPvuDHaGfILjraOKU4" alt=""><figcaption></figcaption></figure>

To get the `Personal Access token`, click on your profile picture and then go into `User settings`.&#x20;

<figure><img src="/files/JntDYwBoc4oNqNz4hrXO" alt="" width="520"><figcaption></figcaption></figure>

From here click on the `Applications` tab, navigate to the Personal access tokens section and click on `New access token`. Make sure you save the access token as you wont be able to access it later.&#x20;

<figure><img src="/files/vfrdbkKM9jXSuMy16I3j" alt="" width="563"><figcaption></figcaption></figure>

##

## CircleCI

While we can deploy our application through Netlify, we would be unable to run tests on our application, to make testing possible, we can hand deployment over to CircleCI. Using this tool we will build and deploy our Application using the Netlify domain, it should be noted we will need to setup CircleCI with the same environment variables that we made for Netlify.&#x20;

Now that we have ensured that we have a working version of our repository on Netlify, we can begin to setup this application on CircleCI. <mark style="color:red;">**The first step that we need to do is change the branch back to the main branch**</mark><mark style="color:red;">.</mark> Then we can add a `.circleci` directory into the root of the project folder structure. Inside here we will generate a `config.yml` file, this file will contain our configuration and workflow.&#x20;

Please populate the `config.yml file` with the configuration below:

````yaml
```yaml
version: 2.1
jobs:
  build:
    working_directory: ~/repo
    docker:
      - image: cimg/node:18.17.0
    steps:
      - checkout
      - run:
          name: Update NPM
          command: "sudo npm install -g npm"
      - restore_cache:
          key: dependency-cache-{{ checksum "package-lock.json" }}
      - run:
          name: Install Dependencies
          command: npm install
      - save_cache:
          key: dependency-cache-{{ checksum "package-lock.json" }}
          paths:
            - ./node_modules
      - run:
          name: Build React App
          command: npm run build
      - save_cache:
          key: app-build-cache-{{ .Branch }}
          paths:
            - ./build
      - run:
          name: Deploy to Netlify
          command: ./node_modules/.bin/netlify deploy --site $NETLIFY_SITE_ID --auth $NETLIFY_ACCESS_TOKEN --prod --dir=dist
workflows:
  version: 2
  build-deploy:
    jobs:
      - build:
          filters:
            branches:
              only:
                - main

```
````

You can push this new directory and file to the main branch on GitHub. We will discuss this configuration later on in the walk through.

Next, navigate to the CircleCI application online, if you've not created an account please do so now and link it to your GitHub repositories. Once this is complete, click on the `Projects` tab, we are then able to see a list of all connected repo that we can deploy using Netlify. Choose the repo you wish to deploy and click `Set Up Project`:

<figure><img src="/files/VHS0kf14NFgiPwEhq0jD" alt="" width="563"><figcaption></figcaption></figure>

Select the main branch

<figure><img src="/files/YSiEz0eknCWUoxZoX4SB" alt="" width="563"><figcaption></figcaption></figure>

This will start a build that will ultimately fail, this is because we have yet to add in the Netlify credentials that we saved previously. To do this we will need to populate this projects Environmental Variables, click on the three dots and to Project Settings:

<figure><img src="/files/hh7Rb5jDD3QFzjgVv009" alt=""><figcaption></figcaption></figure>

Add in the `APP_ID` and `PERSONAL_ACCESS_TOKEN` that we retrieved from Netlify name them:

NETLIFY\_SITE\_ID and NETLIFY\_ACCESS\_TOKEN respectively. These environmental variables are required such that CircleCI can trigger deployments through Netlify. In addition to these you will also need to create and store all the credentials in your .env that you pasted in the Netlify project to connect Firebase.

<figure><img src="/files/cMb0sMnIrHTrESOepxa7" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/Qh69VFFuXDMwa6mggswf" alt="" width="563"><figcaption></figcaption></figure>

<figure><img src="/files/6hHkAhpjrQfvccTwPaI8" alt=""><figcaption></figcaption></figure>

At this point you should be able to edit your code locally and push to the main branch. With this setup, we are building and deploying using CircleCI, CircleCI in turn leverages Netlify as a tool. Any push to the main branch will trigger the CircleCI workflow and a redeployment of the current code within the GitHub Repo.&#x20;

Please goto the file Landing.js, please add the H1 statement. Add it within the rendered JSX.

```
<h1>Added with CircleCi</h1>
```

Now push to the main branch,  CircleCI should successfully deploy the changed code as below.&#x20;

<figure><img src="/files/LrZcRyek84abyaw6qVnq" alt=""><figcaption></figcaption></figure>

CircleCI is able to deploy due to the configuration file that we pushed into the main branch earlier. When we push to the main branch CircleCI clones the target branch (main), then all of the projects dependencies are installed and cached. CircleCI can then trigger the React command `npm run build`. Creating a production build within the `build` folder within the root of the project. This whole folder is then cached to be used later by CircleCI.

CircleCI then triggers the Netlify CLI, which deploys the new site using the `$NETLIFY_SITE_ID` as well as `$NETLIFY_ACCESS_TOKEN`, that we set within CircleCI. Only pushes to the main branch will trigger this work flow.&#x20;

This is how you can develop a continuous deployment for your React frontend. If you alter the configuration file that we setup for CirleCI as well as implement tests into your application you would be able to run tests before it is deployed. By setting up CircleCI you are able to automate deployment and shorten  your development processes by automating testing and deployment.&#x20;




---

[Next Page](/llms-full.txt/1)

