This is the curriculum for the 2018 Foxtrot Web Developer Bootcamp.

What is React? from LEARN on Vimeo

ReactJS

What is Reactjs?

React is a Javascript library for building user interfaces. We can use it to
build webpages, mobile web pages, and even native mobile applications. It is
component based, which means that we use it to build many small parts, and then
join them together to form entire applications. This turns out to be extremely
scalable. It was created from Facebook as that application grew and
became more dynamic.

Read the docs

React has great documentation for just starting with the framework, and as you grow into bigger and more complex applications. You'll want to bookmark their documentation, and refer to it often.

React Documentation

What does a React Webpage look like?

We'll start with an app that is composed of just a single component, and from
there build out more useful and engaging features for our users. Everything in React is a component, from the outer most container of the whole page, to a single line of text or button, its all components, and every component that is visible on the page has a render function.

Here's a complete React application, containing just one component, with one line of text:

public/index.html

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
    <title>React App</title>
  </head>
  <body>
    <div id="root"></div>
  </body>
</html>

In the HTML file, the entire app renders into one element on the page. In our example, we give the div an id of 'app' so we can find it later.

src/App.js

import React, { Component } from 'react';

class App extends Component {
  render() {
    return (
      <h1>Hello LEARN</h1>
    );
  }
}

export default App;

src/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import './index.css';

ReactDOM.render(
  <App />,
  document.getElementById('root')
);

NPM Package Manager from LEARN on Vimeo

NPM package manager and package.json

One of the powerful parts of Node.js is the robust ecosystem of libraries and modules available to build our applications with. We gain access to these modules through Node.js' built in package manager called NPM (Node Package Manager). NPM modules are common functionality wrapped up in a module, and able to be used in different applications.

Some examples of useful NPM Modules:

  • Express - A web development framework
  • Socket.io - Cutting edge websocket functionality for web apps
  • Pug / Jade - Templating engines to make writing HTML easier
  • Mongo / Mongoos - Database wrappers
  • Date.js - Make working with Dates much easier

Creating a Node.js application with package.json

Up to this point, all of our applications have been contained in a single file. As our apps grow, we're going to want to break parts of it out into their own files so things stay nice and organized. Also, as we start to use the functionality of 3rd party NPM modules, we're going to need a way to tell our application what modules we're using. All Node.js apps have a file located right in the root of the project to keep all of that information in one spot called package.json.

We're going to start building towards fully functional web server, but first let's create a new Node.js app with a package.json file, and see what we get. First make a directory called yarn-demo and cd into it. Then run yarn init. It should look like this.

$ yarn init
yarn init v0.24.4
question name (yarn-example):
question version (1.0.0):
question description:
question entry point (index.js):
question repository url:
question author:

question license (MIT):
success Saved package.json
  Done in 4.85s.

Looking at the package.json file it created for us

package.json

{
  "name": "yarn-example",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT"
}

We used Yarn to create a brand new app, and generate a simple package.json file. So far, our app has little more than a name. The other important line in package.json so far is "main": "index.js",. That line tells Node.js what file we want the entry point to our application to be. That file doesn't exist yet, so lets create it now.

// ./index.js

console.log("I have the super powers of a Node.js developer!")

Now, if we go to the command line, and type:

$ node .
I have the super powers of a Node.js developer!

We see that we have started up Node.js, and it knew what file to look in to begin running the program. Pretty neat!

Now, lets do something a little more super with our superman app. We're going to create some ASCII art for this example. Make sure you are inside the super-man-server directory, then:

$ yarn add asciify
 yarn add asciify
yarn add v0.24.4
info No lockfile found.
[1/4]   Resolving packages...
[2/4]   Fetching packages...
[3/4]   Linking dependencies...
[4/4]   Building fresh packages...
success Saved lockfile.
warning Your current version of Yarn is out of date. The latest version is "0.27.5" while you're on "0.24.4".
info To upgrade, run the following command:
$ npm upgrade --global yarn
success Saved 8 new dependencies.
 ansi-styles@0.2.0
 asciify@1.3.5
 chalk@0.3.0
 has-color@0.1.7
 minimist@0.0.10
 optimist@0.6.1
 pad@0.0.4
 wordwrap@0.0.3
  Done in 2.24s.

So what just happened? Yarn installed the module we asked for, asciify, and all of the modules that asciify depends on. Here's a closer look at what Yarn did:

{
  "name": "yarn-example",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "dependencies": {
    "asciify": "^1.3.5"
  }
}

See how it added 'asciify' as a dependency for our project? That means that when we share this project, or go to deploy it, yarn will forever know that it needs asciify to be installed in order to run.

When we run the command "ls", we can see that it also added a "node_modules" directory, and inside that, install asciify as well as all of the libraries that it depends on. Looks like we're all set to start creating some super ASCII art. Lets give it a whirl in our index.js file.

// ./index.js

let asciify = require('asciify')

const text = "Up Up And Away!"

// asciify is a function that accepts parameters, telling it what we want to do.
// The last parameter is a function, known as a 'callback'.  The callback is run
// once asciify has completed, or errored out.
asciify(text, {font: 'larry3d'}, function(err, result){
  if(err){
    console.log("Sorry, we couldn't generate that art")
  } else {
    console.log(result)
  }
})

And the result when we type $ node . on the command line again:

Up, Up, And Away!

Now were cooking! You can read more about asciify on its Github page

Create-React-App from LEARN on Vimeo

Start a new React App

Up until late 2016, the hardest part about working with React was just getting a new app set up. Facebook recognized this problem, and released some tools to help developers get started easily. The following command is one of those tools, and we'll be looking at
some of the important things it does for us - but just to get started, lets try it out now.

create-react-app

Use Yarn to install the create-react-app, so we can build our first React app.

$ yarn global add create-react-app
$ create-react-app sample-app

This creates a directory called 'sample-app' in the current directory and
installs all the files we'll need to get started. Change into the new
directory, and fire up your new app.

Start the webserver

$ cd sample-app
$ yarn start

Check your browser. You've created your first ReactJS app!

There are some instructions there to help us get started. Let's open 'src/App.js' and see what it contains. Go ahead and leave the server that we started with npm start running, and open a new terminal window. Every time we save our work, the server will notice the changes, and reload the page. Pretty neat!

Modifying The App component

src/App.js

// We're using React and Component from the react library
import React, { Component } from 'react';

// We're using webpack to load assets in our project, so loading images
// works much like CSS. We can import them much like any other file.
import logo from './logo.svg';

// The main css file this app uses
import './App.css';

// We create a new component that extends the Component class, which React provides
class App extends Component {

  // When the component is first put on the page, and every time something changes in our component, the render function is     called.  This function builds the html markup that will be put on the page by React.
  render() {

    // Here we have HTML markup right in our .js file.  Most of the React
    // apps that you see, and all of the ones that we'll build in class
    // use something called JSX to preprocess HTML (XML actually) back
    // into plain old JavaScript before the file is sent to the browser.
    // Its not absolutly necessary to use JSX with React, but it makes it
    // so much easier to write React components.
    return (
      <div className="App">
        // Why 'className' instead of 'class'?  It was a design decision on the
        // part of the React development team.  There is lots of great
        // discussion about this on the web around this if you are interested.
        // The important thing to recognize here is that everything is
        // a component in React, so what is really happening here is the div
        // component recieves an attribute named 'className', and is able to
        // operate on it as it is being rendered to the screen.
        <div className="App-header">

          // Notice the '{logo}'.  Everything inside the '{}' when using
          // JSX is evaluated as plain JavaScript.  This line just access
          // the content of the variable 'logo' in our component which we
          // imported above.
          <img src={logo} className="App-logo" alt="logo" />
          <h2>Welcome to React</h2>
        </div>
        <p className="App-intro">
          To get started, edit <code>src/App.js</code> and save to reload.
        </p>
      </div>
    );
  }
}

export default App;

Edit this file to make it our own, and save it. The browser will reload
showing our changes. We'll remove all of the boilerplate that we got for
free when we ran 'create-react-app'


import React, { Component } from 'react';

class App extends Component {
  render() {
    return (
      <div>
        <h1>Hello World!</h1>
      </div>
    );
  }
}

export default App;

Save, and check the browser. The app is now a lot more plain looking compared
to what create-react-app gave us, but this is a big step forward. We're now
building out our own component. We'll be adding all kinds of interesing things
to our app soon enough.

Review

  • React is component-based. What does that mean?

  • What are the advantages of using React?

Exercise

  1. Use create-react-app to create a project.

  2. Find 'App.js' and change some content.

    • Change the h2 contents.
    • Change the div contents.
  3. Find 'App.css' and change some styles.

    • Change the background color of the header.
  4. Find 'index.html' and change the title of the page.

  5. Check out the create-react-app docs on github.

    • Find the 'Adding Bootstrap' section and add Bootstrap to your app
    • Use the given example to add a nav and jumbotron to your component
    • Customize nav and jumbotron

Yarn from LEARN on Vimeo

Yarn

Yarn is a package manager, like NPM, released by Facebook. It works very similarly to NPM, and is the package manager that create-react-app uses. You use it in place of NPM completely.

Commands

NPM Yarn
npm install yarn
npm install --save yarn add

The two most important commands we'll need to use with yarn are to install packages. Listed above are the NPM commands you are already familiar with, and the Yarn equivalents.

Props

Props are how we communicate between components in a React app. We use props to pass data down to a nested component. Take, for example, passing a 'name' into the Header of our application.

src/App.js

import React, { Component } from 'react'
import Header from './Header'
import Recipes from './Recipes'
import Footer from './Footer'

class App extends Component {
  render() {
    return (
      <div>
        <Header name="Matt" />
        <Recipes />
        <Footer />
      </div>
    );
  }
}

export default App;

We can then use the prop in Header

src/Header.js

import React, { Component } from 'react';

class Header extends Component {
  render() {
    return (
      <header>
        <h1>Hello {this.props.name}</h1>
      </header>
    );
  }
}

export default Header;

State

State is a related concept, but it internal to a component, and not shared. We can define state on each component, but in order to do so, we need to get comfortable with the constructor() method first.

Constructors

Constructors for a class are called each time a new instance of a class is created. By definition, constructors of a React component are passed the props. When using a constructor, we need to remember that the parent class from React Component also has setup work to do, so we need to call super(props) when overridding the constructor.

Let's setup our recipes in the Recipes component using state.

src/Recipes.js

import React, { Component } from 'react';

class Recipes extends Component {
  constructor(props){
    super(props)
    this.state = {
      recipes: [
        {name: 'Meatballs'},
        {name: 'Mac & Cheese'}
      ]
    }
  }

  render() {
    let recipes = this.state.recipes.map(function(recipe){
      return(
        <li key={recipe.name}>{recipe.name}</li>
      )
    })
    return (
      <ul>
        {recipes}
      </ul>
    );
  }
}

export default Recipes;

Looping in render()

In a render function of a component, we are returning a string of HTML markup created for us using JSX. Because of this, we can't loop over an array of values directly, but because render() is a regular old javascript function, we can assign the result of a loop to a variable, and use that in the return from render(). Here's how this works:

  render() {
    let recipes = this.state.recipes.map(function(recipe){
      return(
        <li key={recipe.name}>{recipe.name}</li>
      )
    })
    return (
      <ul>
        {recipes}
      </ul>
    );
  }

Notice how we use .map(function) to build up the values from our array, and then use that in the return from render()

Passing recipes down

Components in a React app generally come in two flavors, they can be pure, or impure (sometimes called 'dumb' and 'smart' components). Pure components recieve data via props, and use that data without making any additions or modifications to that data. The Header component is a great example of a 'pure' component. We pass in a name, and the Header just displays it. The App component, conversly is an 'impure' component. It is where the logic for deciding on what name to display is kept. Impure components manipulate the state of the application by fetching data from the server, or maniuplating data in some other way.

Its best to create impure components very purpousfully, and have as few of them as possible in an application. When we keep data manipulation limited to just a few components, all of the complex logic of the application is kept in one spot. The pure components can then go about their work, knowing that they will have no impact on other components. A good analogy is a bee hive. There is only one queen in charge, and the worker bees are out in the flower fields doing their own thing.

Both Pure and Impure components are necessisary and good to use in an application, as long as we keep their roles distinct.

Queen Bee

So, we'll keep all data operations in the App component, and pass it down into our Pure components, Header, Recipes, and Footer. In order to do that, we need to move the recipes list out of the state of Recipes, and up into App.

src/app.js

import React, { Component } from 'react'
import Header from './Header'
import Recipes from './Recipes'
import Footer from './Footer'

class App extends Component {
  constructor(props){                // <-- Move the recipes setup to state of App
    super(props)
    this.state = {
      recipes: [
        {name: 'Meatballs'},
        {name: 'Mac & Cheese'}
      ]
    }
  }

  render() {
    return (
      <div>
        <Header name="Matt" />
        <div>
          <Recipes recipes={this.state.recipes} /> // <-- Pass recipes list to Recipes in the props
        </div>
        <div>
          <Footer />
        </div>
      </div>

    );
  }
}

export default App;

src/Recipes.js

import React, { Component } from 'react';

class Recipes extends Component {
  // Recipes is 'pure' again because it just responds to the data it was passed in props
  render() {
    let recipes = this.props.recipes.map(function(recipe){  
      return(
        <li key={recipe.name}>{recipe.name}</li>
      )
    })
    return (
      <ul>
        {recipes}
      </ul>
    );
  }
}

export default Recipes;

Review

  • What are props for?

  • What is the difference between 'pure' and 'impure' components?

Exercise

Refactor your React app from the previous exercise.

  1. Pass your Header component a prop and call it within 'Header.js'.

  2. Move your list items into the component's state.

  3. 'Purify' your Content component.

JSX from LEARN on Vimeo

jsx transpiling

So What is JSX?

As we've seen, in JSX we have been using HTML-like syntax along side our Javascript. That's because JSX is a language that extends Javascript so that it can work with HTML-like structures. That's great for us because that means that we can write this in JSX:

var nav = (
    <ul id="nav">
      <li><a href="#">Home</a></li>
      <li><a href="#">About</a></li>
      <li><a href="#">Clients</a></li>
      <li><a href="#">Contact Us</a></li>
    </ul>
);

in place of this:

var nav = React.createElement(
   "ul",
   { id: "nav" },
   React.createElement(
      "li",
      null,
      React.createElement(
         "a",
         { href: "#" },
         "Home"
      )
   ),
   React.createElement(
      "li",
      null,
      React.createElement(
         "a",
         { href: "#" },
         "About"
      )
   ),
   React.createElement(
      "li",
      null,
      React.createElement(
         "a",
         { href: "#" },
         "Clients"
      )
   ),
   React.createElement(
      "li",
      null,
      React.createElement(
         "a",
         { href: "#" },
         "Contact Us"
      )
   )
);

Review

  • What is JSX?

  • What does JSX allow us to do?