Lesson 4 - Web

Follow along with bootcamp-web-project branch master

This repo contains files for a simple ReactJS project.

To run the project:

  1. Install NodeJS v6

  2. Download or Clone the project.

  3. Using the terminal, go to the directory of the project

  4. run npm install

  5. run npm start

  6. On your browser go to localhost:3000

FAQ

What is server.js the file?

This file uses nodejs to run a webpack dev server backend. It starts the port 3000 on localhost. It will watch your files as you change them and reload the server and compile the JS files.

https://webpack.js.org/configuration/dev-server/

What is package.json file?

Contains the npm dependancies for the project that is used when using npm install

What is ReactJS?

It is a JS framework, like angular and ember. Its possible to do MVC within React. But primary React solves for the V in MVC. For bigger applications the M is typically done by external libraries. Such as Redux.

Free tutorial by the creator of Redux - https://egghead.io/series/getting-started-with-redux

Intro to ReactJS

in src/index.js you will find the entry point for the application. The full app is loaded by this one line

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

in src/app.js the App component is declared. It is a simple React component that returns another component CardComponents

import React, {Component} from 'react';
import CardComponents from 'components/cards';

class MyApp extends Component {
  render() {
    return (
      <CardComponents/>
    );
  }
}
export default MyApp;

The class MyApp is inherited by React.Component The imports are required at the top of the file. This is the new system for importing libraries in Javascript/ES6. Only the required imports are loaded and compiled.

The render() function of React is where the JSX and DOM elements are defined for the component. You can also include other react components. This is the V in MVC.

If we look at CardComponents we can see that it renders a card layout.

import React, {Component} from 'react';
import {Card, CardActions, CardHeader, CardText} from 'material-ui/Card';
import FlatButton from 'material-ui/FlatButton';

class CardComponents extends Component {
  render() {
    return (
        <Card>
            <CardHeader
            title="Expandable Card Component"
            subtitle="Subtitle here"
            actAsExpander={true}
            showExpandableButton={true}
            />
            <CardActions>
            <FlatButton label="Action1" />
            <FlatButton label="Action2" />
            </CardActions>
            <CardText expandable={true}>
            Lorem ipsum dolor sit amet, consectetur adipiscing elit.
            Donec mattis pretium massa. Aliquam erat volutpat. Nulla facilisi.
            Donec vulputate interdum sollicitudin. Nunc lacinia auctor quam sed pellentesque.
            Aliquam dui mauris, mattis quis lacus id, pellentesque lobortis odio.
            </CardText>
        </Card>
    );
  }
}
export default CardComponents;

The example Card code is taken from Material-UI - http://www.material-ui.com/#/components/card

The export line at the bottom of the file tells Javascript what the default import for this file is. The file can have many classes. So in this example CardComponents is the default import.

You should see the rendered component above at localhost:3000

Using Fetch to call APIs

The fetch API is a modern way to call APIs using Javascript, there is no need to use $.ajax with jQuery or other libraries. This API can be used for majority of API use cases.

Read the examples and documentation at these links:

https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch

https://davidwalsh.name/fetch

Random User API

We will be using a free API to fetch fake user profiles. See https://randomuser.me/

According to the docs we will use GET request to get the profiles. Using the Fetch API, we can use the following code. It will send a GET request to the Random User API and request 10 profiles and parse the JSON response and then console log the response.

fetch('https://randomuser.me/api/?results=10&seed=bootcamp').then(resp => resp.json()).then(r => {
  console.log(r)
})

Run the above code in your browser, in the developer console.

You should see the following print out

Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}

Object {results: Array(10), info: Object}

We got back an object, that contains 10 results.

The getInitialState method enables to set the initial state value, that is accessible inside the component via this.state.

The render method returns the needed component markup, which can be a single child component or null or false (in case you don't want any rendering).

As soon as the render method has been executed the componentDidMount function is called. The DOM can be accessed in this method, enabling to define DOM manipulations or data fetching operations.

More info here:

https://engineering.musefind.com/react-lifecycle-methods-how-and-when-to-use-them-2111a1b692b1

So lets add the above method to our app.

componentWillMount() {
  fetch('https://randomuser.me/api/?results=10&seed=bootcamp').then(resp => resp.json()).then(r => {
    this.setState({people: r});
  })
}

The fetch API is called and completed in async. When completed it sets the state and fills the people object.

The above people object is only filled in when the fetch API is completed. We need to set a default state for the component.

class MyApp extends Component {
  constructor(props) {
    super(props);
    this.state = {
      people: {results:[]}
    }
  }
}

calling the constructor and setting the state inside, is the same as setting it inside the getInitialState method

When the component loads, it has an empty array of people. Then after the API is called and completed, the people will be filled with new results and the component will call render method again.

To render the results, we need to write a render method

render() {
  return (
    <div>{this.state.people.results.map( person => <PersonCardComponent person={person}/>)}</div>
  );
}

This loops through the results array and returns a PersonCardComponent for each person in the people array

The PersonCardComponent is also passed a property, person.

Understanding Props and State

Props & State

There are two types of data that control a component: props and state. Props are set by the parent and they are fixed throughout the lifetime of a component. For data that is going to change, we have to use state. Setting/Change the state, will cause the component to re-render

Props

Most components can be customised with different parameters when they are created. These creation parameters are called props.Your own components can also use props. This lets you make a single component that is used in many different places in your app, with slightly different properties in each place.

import React, {Component} from 'react';
import {Card, CardActions, CardHeader, CardText} from 'material-ui/Card';
import FlatButton from 'material-ui/FlatButton';
class PersonCardComponent extends Component {
  render() {
    let person = this.props.person;
    return (
        <Card>
            <CardHeader
            title={`${person.name.title} ${person.name.first} ${person.name.last}`}
            subtitle="Subtitle here"
            actAsExpander={true}
            showExpandableButton={true}
            />
            <CardActions>
            <FlatButton label="Action1" />
            <FlatButton label="Action2" />
            </CardActions>
            <CardText expandable={true}>
            Lorem ipsum dolor sit amet, consectetur adipiscing elit.
            Donec mattis pretium massa. Aliquam erat volutpat. Nulla facilisi.
            Donec vulputate interdum sollicitudin. Nunc lacinia auctor quam sed pellentesque.
            Aliquam dui mauris, mattis quis lacus id, pellentesque lobortis odio.
            </CardText>
        </Card>
    );
  }
}
export default PersonCardComponent;

Looking at PersonCardComponent we can see that the props is passed the component and it is available under this.props

We can access this.props.personto access the property we passed in the parent component.

The component is also reassigning the props to a variable for easier access. This is optional.

title={`${person.name.title} ${person.name.first} ${person.name.last}`}

The render function can access the props and the person variable, and it can be used anywhere in the component to render the DOM

Thats the end of the lesson!

You have successfully learnt the basics of ReactJS and calling APIs

Last updated