Introduction to React
Clone or download
Pull request Compare This branch is even with sf-sei-3:master.
Latest commit 45a50c7 Aug 13, 2019
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
images Add files via upload Jan 2, 2019
README.md updated hello to functional component Aug 13, 2019

README.md

Intro to React.js

react-logo

Learning Objectives

  • Explain what a frontend framework is and why they can be helpful in writing more complex applications.
  • Explain what ReactJS is and where it fits in our applications' stack.
  • Explain the component model of web development.
  • Create and render React components in the browser.

Framing

What is a Frontend Framework?

  • A framework is software providing generic functionality and structure that serves as foundation to build and deploy applications.
  • Express is a framework that runs on the server, receiving incoming request from the client, preforming some work that you have defined, and returning some response to the client. Front-end frameworks run in the client's browser, receive input from interactions with the page, perform some work that you have defined, and make any updates necessary.
  • Frameworks can help standardize code, give you additional functionality and performance, and can help get your code off the ground faster.
  • There are many front end frameworks and each go about solving problems of how state is managed, updated, and represented by a view but there are many commonalities.
  • There is a lot of debate over whether frontend frameworks count as frameworks at all -- some people say that they are just libraries and should be referred to as such.

What is ReactJS?

React is a JavaScript library used to craft modern day UI and views for the front-end in web applications.

Selling Point: By modeling small compatible components that focus on just rendering a view, we can move business logic out of the DOM, and therefore improve our app's performance, maintainability, modularity and readability.

Some History

The first thing most people hear about React is "Facebook uses it."

  • First used by Facebook in 2011.
  • Then Instagram in 2012.
  • Went open source in May 2013.

BEHOLD! The OLD FACEBOOK!

2008

old facebook

2011

old facebook

React was born out of Facebook's frustration with the traditional MVC model and how..

  • Re-rendering something meant re-rendering everything (or just a lot).
  • That had negative implications on processing power and ultimately user experience, which at times became glitchy and laggy.

If you want to get a taste of what React is all about, here's an introduction from React.js Conf 2015. Recommend starting around the 8:35 mark and watching until 16:30.

React in MVC

React can be thought of as the "Views" layer.

React will work with any back-end language, but for project 3 and in our in-class examples we will be using Mongoose and Express for the models and controllers.

What is the role of a "view" in a front-end Javascript application? The visual template the user sees, often populated with data from our models.

Components

One comment made about React when it was first open sourced was "Rethinking established best practices" which kind of became the React motto. In React, we want to move away from template pages, away from separating code based purely on file type, and more towards a component-based separation of concerns. Templates vs Components

Templates Page Components Page

WanderOak - Fixed Templates vs. Components

When taking a look at Facebook, you could think of each status post as a mini-component in React. And a list of those updates, is a component that contains several of those mini-components. You could take that one step further and think of the Facebook app, as one giant component with several components within it. (Things like the list of status updates, the friends list, the header, etc...)

Imagine you worked at Facebook when they wanted to shift from using likes to reactions. Using traditional JavaScript, HTML, and CSS the shift would make you have to change your code in a bunch of places. Component based architecture allows us to maintain our code more easily.

Wireframe Wireframe with components

MakeTea - Building Robust Apps with React

Notice the structure of how the various components are nested.

- TubeTracker
    - Network
        - Line
    - Predictions
        - DepartureBoard
            - Trains

TubeTracker contains the application Network displays each line on the network Line displays the stations on a line Predictions controls the state of the departure board DepartureBoard displays the current station and platforms Trains displays the trains due to arrive at a platform

F.I.R.S.T. Components

A React component is built to expect an input and render a UI with it. More importantly, a well-structured component only receives data specific to its purpose.

This is because React follows a more functional approach to programming. For React components under this approach, the same input will always produce the same output.

Best practice is that React components follow the F.I.R.S.T. guidelines

Focused

Components should do one thing and do it well.

Independent

Components should increase cohesion and reduce coupling. Behavior in one component should not impact the behavior of another. In other words, components should not rely on one another.

But they should compliment one another.

Reusable

Components should be written in a way that reduces the duplication of code.

Small

Ideally, components should be short and condensed.

Testable

Because the same input will always produce the same output, components are easily unit testable.

If you're interested, Jest is a popular testing library for React.

Exercise: Identifying Components

  • Break into groups of three and take a look at Facebook, Craigslist, Ebay, or a website of your choice. Identify the visual "components" the website is comprised of. Use markers to draw these out on the wall.

As you're drawing this out, think about the following questions...

  • Where do you see "nested components"? Where do you not?
  • Are there any components that share the same structure?
  • Of these similar components, what is different about them?

Initial Setup

In order to create a new project and to get our development environment setup, we are going to use the Terminal command create-react-app. It will create a new folder in your current directory for the in-class application.

create-react-app is an NPM package also built by Facebook that writes our build dependencies for us so that we can do less configuration. It allows us to use React, JSX, and ES6. It also allows us to import our CSS, it autoprefixes our CSS so that we don't have to worry about cross browser compatibility, it gives us a dev server to run, and it enables hot reloading which updates the code in our browser without us refreshing the page.

It uses Webpack which is a build tool that enables many of the features listed above. It also includes Babel which transpiles our JavaScript from ES6 to be compatible with older browsers. It also includes Autoprefixer for CSS compatibility, ESLint for linting, and Jest for testing.

You can also set up all this yourself, but for now create-react-app allows us to worry more about our code and less about configuration.

$ npm i -g create-react-app
$ create-react-app blog-app
$ cd blog-app
$ code .
$ npm start

Here you will begin setting up a blog app that you will continue working on during this lesson's exercises. For demonstration purposes, We will be creating a simple "hello world" app.

After running $ npm start, we can view the app at http://localhost:3000

create-react-app provides us with all the necessary tools and configuration necessary to start writing React. npm start refers to an included script that starts up the development server.

Along with installing the necessary dependencies, it creates an initial app skeleton that looks like this...

├──README.md
├──  favicon.ico
├──  index.html
├──  node_modules
├──  package.json
└──  src
    ├──  App.css
    ├──  App.js
    ├──  index.css
    ├──  index.js
    └──  logo.svg

Most of the important files, which are primarily the ones where we will be working today, are in the /src directory.

Take some time and look at what's been generated. Specifically look in App.js and index.js

We Do: Hello World - A Very Basic Component

The basic unit you'll be working with in ReactJS is a component.

  • Components can be thought of as functional elements that take in data and as a result, produce a dynamic UI.

Throughout class we have separated HTML, CSS and Javascript.

  • With components, the lines between those three become a bit blurry.
  • Instead, we organize our web apps according to small, reusable components that define their own content, presentation and behavior.

What does a component look like? Let's start with a simple "Hello World" example...

To start, in our /src/App.js file, let's remove the contents and in its place add this component definition...

// bring in React from React
import React from 'react'

// define our Hello functional component
function Hello() {
// what should the component render
  return (
  // Make sure to return some UI
    <h1>Hello World!</h1>
  );
}

export default Hello

Let's break down the things we see here...

function Hello

This is the component we're creating. In this example, we are creating a "Hello" functional component.

extends Component

This is the React library class we inherit from to create our component definition.

return

Every component has, at minimum, a render method. It generates a Virtual DOM node that will be added to the actual DOM.

  • Looks just like a regular ol' DOM node, but it's not yet attached to the DOM. In this example the return is handling this functionality.
export default Hello

This exposes the Hello class to other files which import from the App.js file. The default keyword means that any import that's name doesn't match a named export will automatically revert to this. Only one default is allowed per file.

JSX

Hey you got your html in my javascript!

You got your javascript in my html!

(https://youtu.be/O7oD_oX-Gio?t=5s)

Let's talk about the value that the render method returns. It looks an awful lot like an HTML heading, but it's not. We often write out React components in JSX.

JSX is a language that compiles to Javascipt that allows us to write code that strongly resembles HTML. It is eventually compiled to lightweight JavaScript objects.

Your Hello component's render method:

  • Currently returns JSX, not HTML. The JSX creates a heading with 'Hello World!'.
  • Your component reads this and renders a "Hello World!" heading.

React can be written without JSX. If you want to learn more, check out this blog post.

Here is an example of React code without JSX-

Templates Page

Virtual DOM

You may have noticed that our src/index.js code mentions ReactDOM. ReactDOM doesn't refer to the same DOM we know. Instead, it refers to a Virtual DOM. The Virtual DOM is a key piece of how React works.

The Virtual DOM is a Javascript representation of the actual DOM. The virtual DOM is a staging area for changes that will eventually be implemented.

  • Because of that, React can keep track of changes in the actual DOM by comparing different instances of the Virtual DOM.
  • React then isolates the changes between old and new instances of the Virtual DOM and then only updates the actual DOM with the necessary changes.
  • By only making the "necessary changes," as opposed to re-rendering an entire view altogether, we save up on processing power.
  • This is not unlike Git, with which you compare the difference -- or diff -- between two commits.

Virtual DOM Diagram

If you're interested in learning more about the Virtual DOM, check this video out.

So we've created the template for our component. Now, let's use /src/index.js to load in our new component and render it on the DOM...

import React from 'react'
import ReactDOM from 'react-dom'
import Hello from './App.js'

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

In place of ReactDOM.render some tutorials will use React.renderComponent, which has been phased out. The change is outlined here.

ReactDOM.render takes the Virtual DOM node created by extends Component and adds it to the actual DOM. It takes two arguments...

  1. The component.
  2. The DOM element we want to append it to.

NOTE: Whenever you use a self-closing tag in JSX, you MUST end it with a / like <Hello /> in the above example.


Hello World: A Little Dynamic

Our Hello component isn't too helpful. Let's make it more interesting.

  • Rather than simply display "Hello world", let's display a greeting to the user.
  • So the question is, how do we feed a name to our Hello component without hardcoding it into our render method?

First, we pass in data wherever we are rendering our component, in this case in src/index.js...

import React from 'react'
import ReactDOM from 'react-dom'
import Hello from './App.js'

ReactDOM.render(
  <Hello name={"Nick"} />,
  document.getElementById('root')
)

Then in our component definition, we have a reference to that data via as a property on the props object...

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

In the above example, we replaced "world" with {this.props.name}.

What are .props?

Properties! Every component has .props

  • Properties are immutable. That is, they cannot be changed while your program is running.
  • We define properties in development and pass them in as attributes to the JSX element in our .render method.

First we can pass multiple properties to our component when its rendered in src/index.js..

import React from 'react';
import ReactDOM from 'react-dom'
import Hello from './App.js'

ReactDOM.render(
  <Hello name={"Nick"} age={24} />,
  document.getElementById('root')
)

Then in our component definition we have access to both values...

fuction Hello () {
    return (
      <>
        <h1>Hello {this.props.name}</h1>
        <p>You are {this.props.age} years old</p>
      </>
    )
}

NOTE: The return statement in render can only return one DOM element. You can, however, place multiple elements within a parent DOM element, like we do in the previous example with <div>.


You Do: A Blog Post

Let's have some practice creating a React component from scratch. How about a blog post?

  • Create a post object literal in src/index.js above ReactDOM.render() that has the below properties.
    1. title
    2. author
    3. body
    4. comments (array of strings)
  • Render these properties using a Post component.
  • The composition of your Post is up to you.

If you finish early, try experimenting with CSS (Make Sure you use className instead of class in JSX!)

Solution


Q: What problems did you encounter when trying to add multiple comments to your Post?

It would be a pain to have to explicitly define every comment inside of <Post />, especially if each comment itself had multiple properties.

  • This problem is a tell tale sign that our separation of concerns is being stretched, and it's time to break things into a new component.

We can nest a Comment component within a Post component.

  • We create these comments the same way we did with posts: extends Component and render
  • Then we can reference a comment using <Comment /> inside of Post's render method.

Let's create a new file for our Comment component, src/Comment.js...

import React, {Component} from 'react'

class Comment extends Component {
  render () {
    return (
      <div>
        <p>{this.props.message}</p>
      </div>
    )
  }
}

export default Comment

Then in src/App.js, we need to load in our Comment component and render it inside of our Post component...

import React, { Component } from 'react';
// Load in Comment component
import Comment from './Comment.js'


class Post extends Component {
  render() {
    return (
      <div>
        <h1>{this.props.title}</h1>
        <p>By {this.props.author}</p>
        <div>
          <p>{this.props.body}</p>
        </div>
        <h3>Comments:</h3>
        // Render Comment component, passing in data
        <Comment message={this.props.comments[0]} />
      </div>
    );
  }
}

export default Post;

Note: We could put all of our code in one file, but it's considered a good practice to break components out into different files to help practice separation of concerns. The only downside is we have to be extra conscious of remembering to export / import each component to where it's rendered.

The above code works, but we'd have to hard-code all of our Comments. This is not very dry and our code will not dynamically change. The best way to handle this is to set a variable equal to all of the <Comments /> for this post. We can do this using .map in Post's render method.

We can use .map in Post's render method to avoid having to hard-code all of our Comments

class Post extends Component {
  render() {
    let comments = this.props.comments.map((comment, index) => (
      <Comment message={comment} key={index}/>
    ))
    return(
      <div className='post-page'>
        <h1>{this.props.title}</h1>
        <h2>By {this.props.author}</h2>
        <p>{this.props.body}</p>

        <h3>Comments</h3>
        {comments}
      </div>
    )
  }
}

Closing

  • Why do we use components in React?
  • What is the Virtual DOM?
  • What is JSX?
  • What features does create-react-app give us?