Learning React - Week 4
Tags: react, javascript, beginners
Published: 2017-08-03 04:30:28

---
title: Learning React - Week 4
published: true
description: Join me as I learn React in 30 minutes for 30 days with the 'React for Beginners' course by Wes Bos.
tags: react, javascript, beginners
---

This article originally appeared on [stef.ninja](https://stef.ninja/learning-react-week-4/).

This is the final post in my [blogging driven learning](https://dev.to/tamrrat/blogging-driven-learning) exploration of [React](https://facebook.github.io/react/). I have been working through the [React for Beginners](https://reactforbeginners.com/) course from [Wes Bos](https://twitter.com/wesbos) and documenting my takeaways from each lesson. 

This is an **AWESOME** course and I highly recommend it to anyone looking to learn React.

You can find more notes in [Week 1](/learning-react-week-1/), [Week 2](/learning-react-week-2/) and [Week 3](/learning-react-week-3/) of the series.

---

###Day 22: Animating React Components
Animations are a fun way to inject movement into our webpage. This can be done via the traditional method of css (like the GIF below) or some more interactive React animations that we will explore further.

![CSS Animation](https://s3-ap-southeast-2.amazonaws.com/ghost-blog-stef-ninja/2017/07/css_animation-1500949974188.gif)


######NPM Scripts & CSS Preprocessors

Today's lesson touched on a few new concepts including the use of [styl](https://github.com/tj/styl) as a CSS preprocessor. We also explored how this can be integrated in the npm scripts to enable hot reloading during development.

Using the npm scripts in the `package.json` we are able to call `$ npm run watch` in the terminal. It will then concurrently run `start` & `styles:watch`. Then if one of them breaks it's going to kill the other one and show an error in the terminal. This makes development really easy.

This is what the npm scripts look like at this point:

![npm scripts](https://s3-ap-southeast-2.amazonaws.com/ghost-blog-stef-ninja/2017/07/webpack_scripts-1500949986757.png)

Note: In our development environment at work we don't use external CSS or CSS preprocessors as we have opted for [styled components](https://github.com/styled-components/styled-components) (I talked more about this in [Day 4](https://stef.ninja/learning-react-week-1/)).

######Animations

Now that we have our styling options sorted out we can get into the meat of animating React Components.

Our aim today is to animate our order with some subtle movements:

- When a new fish is added to the order it should animate in.
- When a fish is removed from an order is should animate out.
- When the number of lbs of a fish increases the number should animate up.

These are only small movements and we will do a lot of work to make them happen but the polished finish that they give the website is a nice touch.

The first step we need to do is open up our HTML to include classes that we can hook into for our animations. You can do this using the CSSTransitionGroup.

We modified the `ul` component to be a `CSSTransitionGroup` component instead. This looks like this in the code:

![CSSTransitionGroup](https://s3-ap-southeast-2.amazonaws.com/ghost-blog-stef-ninja/2017/07/csstransitiongroup-1500950054510.png)

Note: By adding the `component="ul"` this tells React that we want the component to render a unordered list component in HTML but maintain it as a ReactCSSTransitionGroup in React.

The additional attributes on the `CSSTransitionGroup` component control temporary classes on the `ul` HTML component. You can see how these classes display via the developer tools:

![Temporary classes rendered by the CSSTransitionGroup](https://s3-ap-southeast-2.amazonaws.com/ghost-blog-stef-ninja/2017/07/CSSTransitionGroup-1500950070552.gif)

These temporary classes can then be hooked into via CSS. We are able to use [CSS Transitions](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Transitions/Using_CSS_transitions) because there is an initial state (class `order-enter`/`order-leave`) and a final state (class `order-enter-active`/`order-leave-active`) that we can reference.

These can then be styled like this:

![Styles](https://s3-ap-southeast-2.amazonaws.com/ghost-blog-stef-ninja/2017/07/styles-1500950094516.png)

**Note: the lack of `{}, : or ;` in the `.styl` documents**

This renders out animations that look great:

![Animations first step](https://s3-ap-southeast-2.amazonaws.com/ghost-blog-stef-ninja/2017/07/animations_first_step-1500950104227.gif)

The final task in todays lesson is to animate the count of the lbs for each fish in the order. The animation that we are aiming for looks like the previous number is being pushed out by the new number. This requires a duplication of the element that will let us animate the 'old' version of the element out whilst simultaniously animating the 'new' version of the element in.

This animation style requires us to duplicate the `{count}` span. To do this we will add a `key` attribute with the value `{count}` as well as wrap the `{count}` in a `CSSTransitionGroup` and additional `span`. The code looks like this:

![Count code](https://s3-ap-southeast-2.amazonaws.com/ghost-blog-stef-ninja/2017/07/count_span-1500950117834.png)

This results in two spans being created - a new one with an updated `{count}` and a `order-enter-active` class and the original `{count}` that now has a `order-leave-active` class on it.

![Count CSSTransitionGroup in Action](https://s3-ap-southeast-2.amazonaws.com/ghost-blog-stef-ninja/2017/07/count_csstransitiongroup-1500950133063.gif)

Now all that is left is to add the animation styles in:

![Count Animation styles](https://s3-ap-southeast-2.amazonaws.com/ghost-blog-stef-ninja/2017/07/count_animation_styles-1500950148468.png)

######To Do:

* Import CssTransitionGroup from 'react-addons-css-transition-group' into `Order.js`
* Modify the `ul` to be a `CSSTransitionGroup` & add the required attributes.
* Modify the `{count}` to be wrapped in a `CSSTransitionGroup` & set the attribute `key` to `{count}` (so we have a unique reference available).
* Add animation using CSS transitions in the `_animations.styl` document.

######Today the app looks like:
![App on Day 22 of the React for Beginners Course](https://s3-ap-southeast-2.amazonaws.com/ghost-blog-stef-ninja/2017/07/day22_animations-1500950157836.gif)

*[Video 22: Animating React Components]*

###Day 23: PropTypes for the Win

What are PropTypes? They are validators that make sure the data coming into a component is valid. 

Today's lesson covered inserting PropType validations into every component of the app. We used the `React.PropType` to do this which you can read more about [here](https://facebook.github.io/react/docs/typechecking-with-proptypes.html). 

As of React v15.5 we should be using the `prop-types` library instead of the `React.PropTypes`. This moves away from accessing `PropTypes` from the main `React` object which seems to be a common move in React v15.5. Read more about [migrating from React.PropTypes here](https://facebook.github.io/react/blog/2017/04/07/react-v15.5.0.html#migrating-from-react.proptypes).

######To Do:
- Add proptype validators to all components.

######Today the app looks like:
![App on Day 23 of the React for Beginners Course](https://s3-ap-southeast-2.amazonaws.com/ghost-blog-stef-ninja/2017/07/day23-1501456288496.png)

*Note: There is no visual changes that were made in today's lesson.*

*[Video 23: Component Validation with PropTypes]*

###Day 24: Authentication with Firebase
Currently the database and state can be edited by all visitors. This level of authentication and security is too low for a production level app so we really need to reign that back in.

To do this we will create an application that requires you to login with GitHub, Facebook or Twitter before you can edit the Inventory of a store. The first person to login to that store will be saved as the owner of that store (not a super practical realworld workflow but good enough for todays purposes). This authentication is all going to be completed client side with the backend being handled by Firebase.

All of the sensitive API Secrets and Client IDs are going directly into Firebase rather than our client facing app. This adds a level of security that we don't even need to think about.

######Login Authentication with Firebase
Wes makes this look super simple. He follows these steps:
<ol>
  <li>Create a Facebook App with Facebook Login.</li>
  <li>Create a `Sign-in Method` with Facebook enabled on Firebase.</li>
  <li>Copy the `OAuth redirection URI` from the Firebase tab into the Facebook App settings.</li>
  <li>Enable `Embedded Browser OAuth Login` in the Facebook App settings. Save the changes.</li>
  <li>Copy the `App ID` and `App Secret` into the Firebase Facebook authentication settings.</li>
</ol>

You can do a similar process for all of the Sign-in Providers (Email/Password, Google, [Facebook](https://developers.facebook.com/apps), [Twitter](https://apps.twitter.com), [GitHub](https://github.com/settings/applications/new)).

**Connecting to Firebase**

Connecting to Firebase is super simple with the Rebase package that we imported. We simply need to `Import base from '../base';` at the top of our component and we can now connect to Firebase.

It appears that this lesson covers an outdated method of connecting to Firebase.com. The new Firebase console and 3.x SDKs ask for a diferent method. I will explore connecting to Firebase.com using the method that Wes uses and then also the new and updated method. I will need to research how 'Rebase' works with the new vs old method. You can read more about [Upgrading your Web / Node.js app from Firebase.com](https://firebase.google.com/support/guides/firebase-web).

The Firebase.com method of Authentication via OAuth is:
```
ref.authWithOAuthPopup("twitter", function(error, authData) {
  if (error) {
    // An error occurred
    console.error(error);
  } else {
    // User signed in!
    var uid = authData.uid;
  }
});
```
This can be compared to the new Firebase Authentication functionality that lives behind the `firebase.auth()` service. There have been heaps of methods that have been renamed in this transition and the way that you authenticate users with OAuth is one of those:
```
var auth = firebase.auth();

var provider = new firebase.auth.TwitterAuthProvider();
auth.signInWithPopup(provider).then(function(result) {
  // User signed in!
  var uid = result.user.uid;
}).catch(function(error) {
  // An error occurred
});
```
**Securing Firebase**

Earlier in our lessons we opened the security rules of our Firebase database right up. This was to help with ease of development. Now that we are nearing production release we need to close these right down.  Wes provided sample rules for this in `security-rules.json`:

These rules don't allow people who know the syntax of Firebase to edit it in a destructive manner. So the first rule doesn't allow anyone to delete currently existing data but allows all data to be read. The second rule only allows the store owner to edit data that already exists.

```
{
  "rules": {
    // won't let people delete an existing room
    ".write": "!data.exists()",
    ".read": true,
    "$room" : {
      // only the store owner can edit the data
      ".write" : "auth != null && (!data.exists() || data.child('owner').val() === auth.uid)",
      ".read" : true
      }
  }
}
```


######To Do:
- Create GitHub, Twitter & Facebook sign up methods in the `Auth` section of Firebase.
- Create a method to render out the login buttons in the `Inventory` component.
- Put a conditional statement into the `Inventory` render method.
  - Check if the user is logged in. If not, return the `renderLogin` method.
  - Check if they're the owner of the current store. If not, return a 'Sorry you're not the owner' & 'Logout' button.
  - If they pass both of these checks the user must be logged in & the owner of the current store. So, we will leave the default return in place.
- Set the default state of the `uid` & `owner` to `null` (in the Constructor method).
- Create & bind an `authenticate` method that takes in `provider`. Import base (to connect to Firebase). Use the `base.AuthWithOAuthPopup` method.
- Create & bind an `authHandler` method that handles errors & returns the User information payload from Firebase. Store the User Information in the state.
- Pass the `storeID` down from `App` to `Inventory` via props.
- Grab the store information from Firebase.
- Check whether the store has an owner set, if not, set the current user as the owner.
- Hook into the `componentDidMount` lifecycle method and check to see if there is an authenticated user present. If so, call the `authHandler` method.
- Hook up the `Log Out` button.
- Increase the security of the database rules in Firebase.


######Today the app looks like:
![App on Day 24 of the React for Beginners Course](https://s3-ap-southeast-2.amazonaws.com/ghost-blog-stef-ninja/2017/07/day24-1501467423406.png)

*This will be the last image I put up detailing the App progress as the final lessons are around deployment (with no visual changes).*

*[Video 24: Authentication]*

###Day 25: Building React for Production

`create-react-app` has a build step. It is as simple as running the command `npm run build` in the terminal. This process exports all of the files that we will need to run our app in production. This includes minifying the JS and CSS files and creating source-maps for our JS and CSS. These source-maps will make debugging our app 100% easier by referencing the JS or CSS file that the code was written in rather than the compiled line.

It also outlines how to upload and run this on both a local and a remote server.

![Terminal output after running npm run build](https://s3-ap-southeast-2.amazonaws.com/ghost-blog-stef-ninja/2017/08/terminal_output_from_npm_run_build-1501644417629.png)

The `create-react-app` output at the top level is `index.html` and a `static` folder. This output doesn't come with an actual server. This means that if we just uploaded these files onto a server we would be served a bunch of errors. We need a server that knows to serve the `index.html` regardless of the URL and that relinquishes the routing to the browser.

The next few lessons will be covering how to deploy this app onto various servers that fit this bill. As these are all related to building React for Production I will complete them all today.

#####Deploying to now.sh
[now.sh](https://zeit.co/now) publishes your JavaScript (Node.js) or docker powered apps, websites and services in the cloud easily, quickly and reliably. It also comes with free open source hosting. This means deployment of anything you're happy to open source is quick, free (up to a limit) and easy. 

The `now-serve` (found [here](https://github.com/zeit/now-serve)) command that Wes uses is depreciated and instead we are directed to use `now-static` (found [here](https://zeit.co/blog/now-static)). I was unable to get this working today and will revisit it after learning the other deployment processes.

######To Do:
- Run `npm run build` command.
- Choose a server to deploy to.
- Deploy to a server.

*[Video 25 & 26: Building React for Production, Deploying to now.sh]*

###Day 26: Deploying to GitHub Pages
Another (hacky) way that we can host our `create-react-app` application is by using [GitHub Pages](https://pages.github.com/).

This process is 'hacky' because we need to work around the fact that our Application will be hosted in a subfolder (rather than the root directory). To account for this before running the build process we need to add `"homepage": "https://YOURGITHUBNAME.github.io/YOURREPONAME"`. We will also need to alter the React Router to account for this subfolder.

GitHub pages doesn't allow you to control the routing for your pages so the suggested (hacky) way around this is to duplicate the `index.html` page and rename the copy as `404.html`. This will mean that everytime the browser receives a 404 code the app is still presented. I hate this as a concept and am immediately taking this page down & deleting this repo.

######To Do:
- Set up a blank GitHub repo.
- Set `homepage` in `package.json`
- Modify `react-router` (in `index.js`) to run in a subfolder. (set the attribute 'basename' equal to the subfolder name). You can do this by getting the variable from the URL with:
```
const repo = `/${window.location.pathname.split('/')[1]}`;
const Root = ()
...
<BrowserRouter basename={repo} >
```
- run `npm run build`
- From the new build directory initialise a new Git Repo (with `git init`).
- Add the remote (with `git remote add origin git@github.com:YOURGITHUBNAME/YOURREPONAME.git`)
- Run `git add -A`, `git commit -m "fishy"`, `git push -u origin master`.
- In the settings of your GitHub repo publish the `master branch` as the source for your GitHub page.
- Duplicate `index.html` as `404.html` & commit & push this change.

*[Video 27: Deploying to GitHub Pages]*

###Day 27: Deploying to an Apache Server
Now we're getting into the good stuff. Today we're deploying on a standard Apache server (like the kind you pick up from GoDaddy or Bluehost for a couple of bucks a month).

If you're going to deploy to a subdirectory (not the root domain or a subdomain) then you will need to update the `react-router` information in `index.js` and the `hompage:` declaration in `package.json`. If not, these additions can be deleted.

We need to tell the server that `index.html` should be served for ALL routes. For an Apache server you can do this with a `.htaccess` file. Enter the following:
```
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME}% !-f
RewriteCond %{REQUEST_FILENAME}% !-d
RewriteRule . /index.html [L]
```
These rules breakdown to - whenever you have ANY `/` serve up either the requested filename OR if nothing is found then serve up `index.html` instead.

Note: To do this for an `nginx` server you could use the following in an `nginx.conf` file:
```
location / {
    try_files $uri /index.html;
}
```

######To Do:
- run `npm run build`
- FTP these files up to your Apache server.
- Create a `.htaccess` file.
- Allow the domain on Firebase (so your login OAuth continues to work)

*[Video 28: Deploying to an Apache Server]*

###Day 28: Property Initializers and Getting Rid of .bind()
Anytime we want to add a custom method that we want bound to the instance of our component we need to use `.bind()` in the constructor method. This is a lot of repeated and convoluted code and in today's lesson Wes shows us how to get rid of it using public class fields that are proposed for future iterations of JavaScript (ES6).

*Note: Wes references the [ES Class Fields & Static Properties](https://github.com/tc39/proposal-class-public-fields) proposal to JavaScript but this has since been merged with another proposal to form the [ESnext class features for JavaScript](https://github.com/tc39/proposal-class-fields).*

So how does these Property Initializers relate to removing `.bind()`?

We can remove this from the `constructor()`:
```
this.loadSamples = this.loadSamples.bind(this)
```

We then alter the method from:
```
loadSamples() {
  this.setState({
    fishes: sampleFishes
    });
}
```
TO:
```
loadSamples = () => {
  this.setState({
    fishes: sampleFishes
    });
};
```
This works because the [arrow function](https://googlechrome.github.io/samples/arrows-es6/) binds to the parent (essentially doing the same work as the `.bind()` we were using earlier with much less hassle). *It is important to note that this is a feature that hasn't been implemented into JavaScript yet and there is no guarantee that it ever will.*

We are also able to remove any state declarations that were made within the `constructor()`:

```
this.state = {
  fishes: {},
  order:{}
}
```
We can then remove the dot notation and set it outside of the `constructor()`:
```
state = {
  fishes: {},
  order:{}
};
```
This is a property Initializer that has been added to every instance of App. This means that every instance of this component will be initialised with this state.

Futher dot notation removal can happen to anything that needs to happen after the component. For example, our propTypes are checked below the `render()` of the component. These can be moved inside the component return and given a `static` flag (as we don't need a new version everytime there is a new instance of this component).
```
App.propTypes = {
  params: React.PropTypes.object.isRequired,
}
```
This can be moved into the `render()` function and modified to:
```
static propTypes = {
  params: React.PropTypes.object.isRequired,
};
```

######To Do:
- Replace `.bind()` Property Initializers.
- Move all `propTypes` into the component & make them static.

*[Video 29: Future React Today - Property Initializers and getting rid of .bind()]*

###Day 29: Throwing Away the create-react-app Parachute
`create-react-app` is brilliant because it handles all of the hard behind the scenes magic (cough webpack cough) and allows you to just get in there and start creating. However, there may be a time where the default set up isn't going to work for you any more and you need to eject from `create-react-app`.

*Warning: There is no way to 'uneject' from create-react-app so make sure you are doing this on a GitHub branch.*

Ejecting from `create-react-app` is as simple as runinng the command `npm run eject`. 

It will then install all of the dependencies that the app needs to work. It will also create two new directories (config & scripts). It will also add a literal butt-tonne of `devDependencies` to your `package.json` file. 

You can now edit and update the webpack config, eslintConfig and babel as needed. 

######To Do:
- Create new `ejected` branch in repo
- Run command `npm run eject`
- Customise as needed.

*[Video 30: Ejecting from create-react-app]*

###Day 30: Deploying to Firebase
It's the last day of my 30 day challenge and I have run out of official `React for Beginners` lessons. The one thing that I was curious about during the last couple of lessons is how we could use Firebase to host the app (as well as handle the persistent state management with the database). I'm also curious if we would be given enough control over the routing to server `index.html` regardless of the location.

With a little bit of quick research I can see that this is not only possible but it looks as though Firebase is built for it. So without further ado, let's get this app deployed onto Firebase hosting.

######Deploying create-react-app to Firebase
The `create-react-app` documentation goes through how to deploy your app to Firebase. Follow the instructions [here](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#firebase) (as they will be better than anything I can describe).

######Customising Hosting Behaviour on Firebase
Firebase opens up the control of how content is hosted - this includes custom error pages, redirects, rewrites and headers. In our case, we're interested in [rewrites](https://firebase.google.com/docs/hosting/url-redirects-rewrites).

To do this I added some customisations to the `firebase.json` document. My additions tell Firebase to make `build` the public directory and redirect all routes to the `index.html` file. It also tells it to ignore the files that don't need to be included in deployment.  

It now reads like:
```
{
  "hosting": {
    "public": "build",
    "rewrites": [{
      "source": "**",
      "destination": "/index.html"
    }],
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ]
  }
}
```

Now you can view my App [here](https://catch-of-the-day-published.firebaseapp.com/) if you ever want to check it out.

######To Do:
- Install Firebase CLI.
- Run the `create-react-app` build command.
- Customise the `firebase.json`
- Deploy to Firebase.

---
Read more in this series: [Week 1](https://stef.ninja/learning-react-week-1/), [Week 2](https://stef.ninja/learning-react-week-2/), and [Week 3](https://stef.ninja/learning-react-week-3/) **Or** get the [React for Beginners Course](https://reactforbeginners.com/) for yourself.