March 3, 2018

/

React Crypto Stock Compare – Pt. 2: Creating Components

React Crypto Stock Compare – Pt. 2: Creating Components

This is to part 2 of a multi-part React tutorial that will teach you the basics of React while building a simple app to compare crypto-currency prices to stock prices. You can find the code to work along here and the starting point for this step can be found in the branch start by running git checkout start

As I said in Part 1 React is a library for building user interfaces. The first question you might have is “what does that actually mean?”. At it’s core, React is based on building components. A component represents a part of your application and when creating an app in React all you are really doing is composing multiple components together to build a user interface.

In short any React app you build or see is just components all the way down… Before I get into the first bit of coding I want to explain what a component is in the context of React.

What is a component?

While component has a generic meaning in everyday speech React has a specific concept of a component. There are a couple of different ways you can create a component but the easiest place to start is by creating a class the extends the React Component class like so:

import React from 'react';
class MyFirstComponent extends React.Component {
  render() {
   return <div>My First Component</div>;
  }
}

There are a few things to say about this simple example. First of all there is the HTML like syntax called JSX in the render method:

<div>My First Component</div>

This lets you write your HTML inside of JavaScript and in my opinion is one of the best thing about React.

The advantage of having direct access to your HTML elements and being able to use plain old JavaScript is massive. In contrast frameworks like Angular that have their own templating language built on top of HTML you can just use JavaScript’s existing functions and syntax to perform manipulation of you data and markup. It is possible to write React without writing JSX but in all seriousness if you want to do that I recommend you use another library like Vue, which is great too, however this tutorial is about React so stay with me!

Another thing to mention about MyFirstComponent it is that it has a render() method. This is the bread and butter of React. React components have what is called a component life-cycle and and part of that life-cycle is to render out the HTML that is represented by your JSX expression in the render method. There are a number of other built in methods on the React.Component class but for now I’m just going to stick to the render method to keep things simple.

Want to code along?

I strongly recommend you code along with the tutorial. I’ve made this easy by setting up a Github repository with all the code and a seperate branch for each of the steps along the way. To get started follow these steps:

Step 1: Install NodeJS and Git

If you don’t already have them installed then you can find them here:

Step 2: Clone the repo

You need to get the code to start with so open a terminal or command window and run the following to copy it from Github to your machine:

git clone https://github.com/sethreidnz/crypto-stock-compare

Step 2: Install the NPM packages needed

From the directory where you ran the git clone command run the following two commands to install the npm packages the project needs:

cd crypto-stock-compare
npm install 

Step 3: Checkout the start branch

The master branch (the default branch) contains the final code, so run the following to change into the start branch to get started:

git checkout start

Whats going on in this app?

First of all I recommend opening the whole folder in your favorite text editor or IDE, personally I use Visual Studio Code. If you open the whole folder you can see all code structure as follows:

Folder Structure

There are a number of folders and files in this app, don’t worry about that, we are going to start by examining two files: src/index.js and src/App.js.

The src/index.js you won’t really have to worry about very often in day to day React development but its worth explaining as this is where your React app gets kicked off:

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

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

Reading from top to bottom, first we import React from the package ‘react’. Simple enough.

Then we import ReactDOM from a package called ‘react-dom’. This is the package we use to to render our React app to HTML also known as “the DOM”.

The next line might seem strange to you if you haven’t done any development using Webpack but what this allows you to do is import CSSin you’re file to indicate that the JavaScript depends on this CSS. Create React App will (via Webpack) take care of this for you so you don’t have to add any CSS links manually into the HTML of your app.

The next line we import the component App (more on that later) from the file in the file ./App.js (the .js can be ommitted for JavaScript files that is why its ‘./App’).

Finally we use ReactDOM.render(), which we pass the component we want to render our React app into. This is just a div in HTML page found in src/public/index.html. If you look at the HTML in there you’ll see there is a div with the id root. This is called “mounting” a component into the DOM. That is all you really need to know about ReactDom or anything in this file! the rest is all just components… all the way down.

Building out App.js

So now that we have mounted the <App /> component have a look at file src/App.js:

import React, { Component } from "react";
import { getEthereumData, getMicrosoftData } from "./api";
import "./App.css";

const ethereumData = getEthereumData();
const microsoftData = getMicrosoftData();

class App extends Component {
  render() {
    return <div>My first component</div>;
  }
}

export default App;

The first few lines are similar to src/index.js except we are importing the Component class and some API functions I have build from the api folder. Then I have two lines where I put the return values of getEthereumData and getMicrosoftData into local variables. These values are arrays containing the each days data for Ethereum and Microsoft.

The component itself is exactly like the one above MyFirstComponent so lets see what happens when we run the app. To do this open up a terminal or command window at the root of the project and run:

npm start

This might take a moment but it will launch the app at http://localhost:3000 and you should see the words “My First Component” on the screen. Simple as that! You have a component.

But this component doesn’t really do much… Lets add some data to our app.

Printing out variables and looping through arrays

Something that you end up doing a lot in any app it taking values from one place, say an API, and then displaying them on the screen. In React you can take that data and build up your HTML dynamically using JSX.

Open up your src/App.js file and replace the whole App class with the following:

class App extends Component {
  render() {
    return (
      <div className="crypto-stock-compare">
        <h1>Crypto Stock Compare</h1>
        <section className="value-table">
          <h2>Ethereum</h2>
          <table>
            <thead>
              <tr>
                <th>Date</th>
                <th>Open</th>
                <th>Low</th>
                <th>High</th>
                <th>Change</th>
              </tr>
            </thead>
            <tbody>
                <td></td>
                <td></td>
                <td></td>
                <td></td>
                <td></td>
            </tbody>
          </table>
        </section>
        <section className="value-table">
          <h2>Microsoft</h2>
          <table>
            <thead>
              <tr>
                <th>Date</th>
                <th>Open</th>
                <th>Low</th>
                <th>High</th>
                <th>Change</th>
              </tr>
            </thead>
            <tbody>
                <td></td>
                <td></td>
                <td></td>
                <td></td>
                <td></td>
            </tbody>
          </table>
        </section>
      </div>
    );
  }
}

So far all I’ve done is created two empty tables but notice that the markup is just like plain old HTML. The only exception is that instead of adding class= you have to add className=.

What we really want to do is take the values from the arrays ethereumData and microsoftData and create a row for each record. To do this you can use the array function map. Map will iterate over each value in an array and create a new array containing the values you return. For a simple example:

const myArray = [1, 2, 3];
const myArray2 = myArray.map(number => number + 1);
// myArray = [2, 3, 4]

We can do the same thing except instead of returning numbers we return JSX. Here is how to create a row out of the ethereumData array:

<tbody>
  {ethereumData.map(dayData => (
      <tr>
        <td>{dayData.date}</td>
        <td>{dayData.open}</td>
        <td>{dayData.low}</td>
        <td>{dayData.high}</td>
        <td>{dayData.change}%</td>
      </tr>
    ))}
</tbody>

This code is just looping through each of the dayData items in the array and returning a row containing the 5 pieces of data: date, open, low, high and change. You might notice that I use curly brackets {} around the map function as well as around the data {dayData.date}. This is how you add regular JavaScript expressions inside of your JSX. Basically {dayData.date} is saying “print out the value of dayData.date here”. You might also notice the user of parenthesis () around the whole thing. That is just syntactic sugar to make it possible to write multiple line JSX expressions easily.

I’m going to improve this a little bit by adding an up or down arrow to indicate if the change was positive or negative:

{ethereumData.map(dayData => {
  const arrowClass = `arrow-${
    dayData.change > 0 ? "up" : "down"
  }`;
  return (
    <tr key={dayData.date}>
      <td>{dayData.date}</td>
      <td>{dayData.open}</td>
      <td>{dayData.low}</td>
      <td>{dayData.high}</td>
      <td>
        <span className={arrowClass} />
        {dayData.change}%
      </td>
    </tr>
  );
})}

Notice how I’m doing a calculation at the beginning of my map function to determine the class name of the span I’ve added next to the change value. If the change is greater than 0 then the class will be arrow-up otherwise it will be arrow-down (I’ve deliberately not handles the case if it was equal to 0 for simplicity sake). I’ve also added key={dayData.date} to the <tr> element which is used by React to keep track of which element is which when you print out an array of elements.

Now that I’ve explained what to do, try replacing the your render method with this:

render() {
  return (
    <div className="crypto-stock-compare">
      <h1>Crypto Stock Compare</h1>
      <section className="value-table">
        <h2>Ethereum</h2>
        <table>
          <thead>
            <tr>
              <th>Date</th>
              <th>Open</th>
              <th>Low</th>
              <th>High</th>
              <th>Change</th>
            </tr>
          </thead>
          <tbody>
            {ethereumData.map(dayData => {
              const arrowClass = `arrow-${
                dayData.change > 0 ? "up" : "down"
              }`;
              return (
                <tr key={dayData.date}>
                  <td>{dayData.date}</td>
                  <td>{dayData.open}</td>
                  <td>{dayData.low}</td>
                  <td>{dayData.high}</td>
                  <td>
                    <span className={arrowClass} />
                    {dayData.change}%
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </section>
      <section className="value-table">
        <h2>Microsoft</h2>
        <table>
          <thead>
            <tr>
              <th>Date</th>
              <th>Open</th>
              <th>Low</th>
              <th>High</th>
              <th>Change</th>
            </tr>
          </thead>
          <tbody>
            {microsoftData.map(dayData => {
              const arrowClass = `arrow-${
                dayData.change > 0 ? "up" : "down"
              }`;
              return (
                <tr key={dayData.date}>
                  <td>{dayData.date}</td>
                  <td>{dayData.open}</td>
                  <td>{dayData.low}</td>
                  <td>{dayData.high}</td>
                  <td>
                    <span className={arrowClass} />
                    {dayData.change}%
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </section>
    </div>
  );
}

That’s it! You’ve created your first real component with data binding and all.

If you got lost or want to make sure you did it right you can have a look in the branch in Github or run:

git checkout creating-basic-component

The next step is to learn how to split up a component into multiple components which is covered in in Pt. 3: Splitting a component into multiple components

Next Step

Tags:

Seth Reid

/

React Crypto Stock Compare – Pt. 2: Creating Components