Getting Started in React the Easy Way

Published Aug 30, 2017
Getting Started in React the Easy Way

In the last post, What You Need to Know in JavaScript, I talked about some required JavaScript knowledge for productivity in a React codebase. Today, we're going to begin our journey into using ReactJS to build a simple and searchable product catalog. This example was extracted from the React documentation, Thinking in React.

Before we begin building our application, we need to set up all of the required libraries.

A simple project layout looks like this:

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>My First React Application</title>
</head>

<body>

  <div id="root">
    <!-- This element's contents will be replaced with your component. -->
  </div>
  <script src="https://unpkg.com/react@15.6.0/dist/react.min.js" 
    crossorigin="anonymous"></script>
  <script src="https://unpkg.com/react-dom@15.6.0/dist/react-dom.min.js" 
    crossorigin="anonymous"></script>
  <script src="https://unpkg.com/create-react-class@15.6.0/create-react-class.min.js" crossorigin="anonymous"></script>
  <script src="https://unpkg.com/babel-standalone@6.24.2/babel.min.js"></script>
  <script type="text/babel" src="./index.js"></script>

</body>

</html>

index.js

const MyApp = createReactClass ({
    render(){
        return <h1>Hello from React {React.version}</h1>  
    }
})

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

We need to ensure that both files are in the same folder. I'll assume our files are in a folder named first-react-app.

We also need to ensure that this project is running on an actual webserver. There are many ways to spin up a webserver, but let's go with a simple approach — assuming we have Python installed.

In our terminal/command prompt, type in the following commands:

# Assumming python 2
cd first-react-app # the name of our project
python -m SimpleHTTPServer

# Assumming python 3
cd first-react-app
python -m http.server  

We should get the following when we visit http://localhost:8000 (8000 is the default port if we don't specify anything)

localhost.PNG

With the above working, we can begin the process of building our actual application. I'll go through the thought process and explain the new constructs we'll run into, as well as the building blocks of our application.

Adding the script tags to our HTML page ensures that React, ReactDOM, and createReactClass are globally accessible to all of our JavaScript files.

In our index.js, we run into a special construct
<h1>Hello from React {React.version}</h1>. This is known as JSX. We can think of it as HTML in our JavaScript file. The Babel scripts include https://unpkg.com/babel-standalone@6.24.2/babel.min.js. This helps convert JSX into actual JavaScript objects. We'll be making use of JSX, because it's very similar to HTML.

I would begin by starting with the end result and working our way back.

I'll remove everything in our index.js and replace it with the following.

const React = window.React;
const ReactDOM = window.ReactDOM;
const createReactClass = window.createReactClass;

const MyApp = createReactClass({
  render() {
    return (
      <div>
        <form>
          <input type="text" placeholder="Search..." />
          <p>
            <input type="checkbox" /> Only show products in stock
          </p>
        </form>
        <table>
          <thead>
            <tr>
              <th>Name</th>
              <th>Price</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <th colSpan="2">Sporting Goods</th>
            </tr>
            <tr>
              <td>Football</td>
              <td>$49.99</td>
            </tr>
            <tr>
              <td>Baseball</td>
              <td>$9.99</td>
            </tr>
            <tr>
              <td>Basketball</td>
              <td>$29.99</td>
            </tr>
            <tr>
              <th colSpan="2">Electronics</th>
            </tr>
            <tr>
              <td>Ipod Touch</td>
              <td>$99.99</td>
            </tr>
            <tr>
              <td>Iphone 5</td>
              <td>$399.99</td>
            </tr>
            <tr>
              <td>Nexus 7</td>
              <td>$199.99</td>
            </tr>
          </tbody>
        </table>
      </div>
    );
  }
});

ReactDOM.render(<MyApp />, document.getElementById("root"));

This is a static implementation of what we're trying to build. We aren't doing anything fancy yet, and most things will still look familar to us.

sample.PNG

MyApp is known as a React Component. We could think of it as our own custom HTML tag that knows how to implement a particular functionality, just like any inbuilt HTML tag.

At the end of the file, we inject our component into the DOM. If we look at our HTML file, there is an empty div element with an id of root. We can access this HTML/DOM element through JavaScript by making use of the inbuilt DOM API document.getElementById and specifying the id of the element as a parameter.

We can experiment within the console tab on the browser running our script to verify that this works.
console.PNG

Assuming we are more familiar with JQuery and are more comfortable using it to query elements from the DOM, then the last line becomes this:
ReactDOM.render(<MyApp/>,$('#root')[0]).
We want to limit our usage of JQuery because ReactJS is a more powerful alternative.

ReactDOM.render is what's responsible for injecting our component into the DOM. It takes in two parameters, the component (in our case MyApp) and the DOM node.

We'll make use of the map to reduce our boilerplate static implementation.

Let's change the implementation of MyApp to the code below.

const MyApp = createReactClass({
  render() {
    const items = [
      { name: "Football", price: "$49.99" },
      { name: "Baseball", price: "$9.99" },
      { name: "Basketball", price: "$29.99" },
      { name: "Ipod Touch", price: "$99.99" },
      { name: "Iphone 5", price: "$399.99" },
      { name: "Nexus 7", price: "$199.99" }
    ];
    const first3Items = items.slice(0, 3);
    const last3Items = items.slice(3, items.length);
    return (
      <div>
        <form>
          <input type="text" placeholder="Search..." />
          <p>
            <input type="checkbox" /> Only show products in stock
          </p>
        </form>
        <table>
          <thead>
            <tr>
              <th>Name</th>
              <th>Price</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <th colSpan="2">Sporting Goods</th>
            </tr>
            {first3Items.map((item, index) =>
              <tr key={"first-item " + index}>
                <td>
                  {item.name}
                </td>
                <td>
                  {item.price}
                </td>
              </tr>
            )}
            <tr>
              <th colSpan="2">Electronics</th>
            </tr>
            {last3Items.map((item, index) =>
              <tr key={"last-item" + index}>
                <td>
                  {item.name}
                </td>
                <td>
                  {item.price}
                </td>
              </tr>
            )}
          </tbody>
        </table>
      </div>
    );
  }
});

In the above implementation, I extracted the actual data as an array of JavaScript objects. I then chose to split the array into two arrays. This is a temporary solution that we'll resolve later, but it's easy to follow for now. Using the map method on array objects, I then transformed each object in the array into a JSX representation. When creating an array of JSX objects, React requires adding a key parameter to the node, which should be unique, hence our custom key attribute.

If we look closely at our current implementation, I'm still duplicating the code below:

<tr key={"last-item" + index}>
    <td>  {item.name}  </td>
    <td>  {item.price}  </td>
  </tr>

We can simplify this by extracting this duplicate and creating a React component out of it, as shown below:

const Row = item => {
  return (
    <tr>
      <td>
        {item.name}
      </td>
      <td>
        {item.price}
      </td>
    </tr>
  );
};

The MyApp component now becomes:

Figure B

const MyApp = createReactClass({
  render() {
    const items = [
      { name: "Football", price: "$49.99" },
      { name: "Baseball", price: "$9.99" },
      { name: "Basketball", price: "$29.99" },
      { name: "Ipod Touch", price: "$99.99" },
      { name: "Iphone 5", price: "$399.99" },
      { name: "Nexus 7", price: "$199.99" }
    ];
    const first3Items = items.slice(0, 3);
    const last3Items = items.slice(3, items.length);
    return (
      <div>
        <form>
          <input type="text" placeholder="Search..." />
          <p>
            <input type="checkbox" /> Only show products in stock
          </p>
        </form>
        <table>
          <thead>
            <tr>
              <th>Name</th>
              <th>Price</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <th colSpan="2">Sporting Goods</th>
            </tr>
            {first3Items.map((item, index) =>
              <Row
                key={"first-item " + index}
                name={item.name}
                price={item.price}
              />
            )}
            <tr>
              <th colSpan="2">Electronics</th>
            </tr>
            {last3Items.map((item, index) =>
              <Row
                key={"last-item" + index}
                name={item.name}
                price={item.price}
              />
            )}
          </tbody>
        </table>
      </div>
    );
  }
});

I created a new component called Row, using an altenative syntax to create a component in React, which is literally just a function. This function takes an object that represents what we want to inject, in this case, the name and the price.

We can completely remove the need for spliting the original array by doing the following

const Category = item => {
  return (
    <tr>
      <th colSpan="2">
        {item.category}
      </th>
    </tr>
  );
};
const MyApp = createReactClass({
  render() {
    const items = [
      { name: "Football", price: "$49.99", category: "Sporting Goods" },
      { name: "Baseball", price: "$9.99", category: "Sporting Goods" },
      { name: "Basketball", price: "$29.99", category: "Sporting Goods" },
      { name: "Ipod Touch", price: "$99.99", category: "Electronics" },
      { name: "Iphone 5", price: "$399.99", category: "Electronics" },
      { name: "Nexus 7", price: "$199.99", category: "Electronics" }
    ];
    let rows = [];
    let lastCategory = null;
    items.forEach((item, index) => {
      if (item.category !== lastCategory) {
        rows.push(<Category category={item.category} key={item.category} />);
      }
      rows.push(
        <Row name={item.name} price={item.price} key={"item" + index} />
      );
      lastCategory = item.category;
    });
    return (
      <div>
        <form>
          <input type="text" placeholder="Search..." />
          <p>
            <input type="checkbox" /> Only show products in stock
          </p>
        </form>
        <table>
          <thead>
            <tr>
              <th>Name</th>
              <th>Price</th>
            </tr>
          </thead>
          <tbody>
            {rows}
          </tbody>
        </table>
      </div>
    );
  }
});

Okay what just happened? Well, it's actually quite simple. I'll explain everything that's happening.

I extracted the category sections into a component called Category. Assuming we were working with Figure B implementation after creating this component, the render section in our MyApp component looks like this:

return (
      <div>
        <form>
          <input type="text" placeholder="Search..." />
          <p>
            <input type="checkbox" /> Only show products in stock
          </p>
        </form>
        <table>
          <thead>
            <tr>
              <th>Name</th>
              <th>Price</th>
            </tr>
          </thead>
          <tbody>
            {<Category category="Sporting Goods" />}
            {first3Items.map((item, index) =>
              <Row
                key={"first-item " + index}
                name={item.name}
                price={item.price}
              />
            )}
            <Category category="Electronics" />
            {last3Items.map((item, index) =>
              <Row
                key={"last-item" + index}
                name={item.name}
                price={item.price}
              />
            )}}
          </tbody>
        </table>
      </div>)

Since all the elements inside the tbody tag are adjacent to each other, i.e.

<Category category="Sporting Goods" />
<Row key="" name="Football" price="$49.99"/>
<Row key="" name="Baseball" price="$9.99" />
<Row key="" name="Basketball" price="$29.99" />
<Category category="Electronics" />
<Row key="" name="Ipod Touch" price="$99.99" />
<Row key="" name="Iphone 5" price="$399.99" />
<Row key="" name="Nexus 7" price="$199.99" />

The above can be represented as an array of JSX tags as long as we remember to add the key attribute to each of them — ReactJS requires this when dealing with an array of JSX tags. We could rewrite our render method in MyApp as the following:

render(){
...
const rows = [
<Category category="Sporting Goods" />,
<Row key="" name="Football" price="$49.99"/>,
<Row key="" name="Baseball" price="$9.99" />,
<Row key="" name="Basketball" price="$29.99" />,
<Category category="Electronics" />,
<Row key="" name="Ipod Touch" price="$99.99" />,
<Row key="" name="Iphone 5" price="$399.99" />,
<Row key="" name="Nexus 7" price="$199.99" />,
]
return (
  <div>
        <form>
          <input type="text" placeholder="Search..." />
          <p>
            <input type="checkbox" /> Only show products in stock
          </p>
        </form>
        <table>
          <thead>
            <tr>
              <th>Name</th>
              <th>Price</th>
            </tr>
          </thead>
          <tbody>
            {rows}
          </tbody>
        </table>
      </div>
)
}

JSX is just JavaScript, so we can manipulate it the way we do to regular JavaScript Objects.

The final thing is to figure out how to transform:

const items = [
      { name: "Football", price: "$49.99" },
      { name: "Baseball", price: "$9.99" },
      { name: "Basketball", price: "$29.99" },
      { name: "Ipod Touch", price: "$99.99" },
      { name: "Iphone 5", price: "$399.99" },
      { name: "Nexus 7", price: "$199.99" }
    ];

into

[
<Category category="Sporting Goods" />,
<Row key="" name="Football" price="$49.99"/>,
<Row key="" name="Baseball" price="$9.99" />,
<Row key="" name="Basketball" price="$29.99" />,
<Category category="Electronics" />,
<Row key="" name="Ipod Touch" price="$99.99" />,
<Row key="" name="Iphone 5" price="$399.99" />,
<Row key="" name="Nexus 7" price="$199.99" />,
]

The first thing I did was I added an extra category field to each object in the array, which yielded this:

const items = [
      { name: "Football", price: "$49.99", category: "Sporting Goods" },
      { name: "Baseball", price: "$9.99", category: "Sporting Goods" },
      { name: "Basketball", price: "$29.99", category: "Sporting Goods" },
      { name: "Ipod Touch", price: "$99.99", category: "Electronics" },
      { name: "Iphone 5", price: "$399.99", category: "Electronics" },
      { name: "Nexus 7", price: "$199.99", category: "Electronics" }
    ];

Then, I created a variable called rows and initialized it as an empty array. This is where we'll end up dumping the transformed items.

I also created a variable lastCategory to hold the value of the current category being worked on.

I then made use of the forEach method available to JavaScript arrays to loop through each of the items in items and populate the rows array.

let rows = [];
let lastCategory = null;
/* Going through each item in the items array*/
items.forEach((item, index) => {
/* I am checking if the category of the first item is equal to the lastCategory.
If not, then I add a Category component to the rows array. */
if (item.category !== lastCategory) { 
rows.push(<Category category={item.category} key={item.category} />);
}
/*For the remaining items, I am coverting them to Row components and adding them to the rows array */
rows.push(
<Row name={item.name} price={item.price} key={"item" + index} />
);
/*I finally updated the value of lastCategory` to the value of the current item category in the loop.*/
lastCategory = item.category;
});

And that is how I arrived at the simplified solution.

index.js

const React = window.React;
const ReactDOM = window.ReactDOM;
const createReactClass = window.createReactClass;

const Row = item => {
  return (
    <tr>
      <td>{item.name}  </td>
      <td> {item.price}  </td>
    </tr>
  );
};
const Category = item => {
  return (
    <tr>
      <th colSpan="2">{item.category}</th>
    </tr>
  );
};
const MyApp = createReactClass({
  render() {
    const items = [
      { name: "Football", price: "$49.99", category: "Sporting Goods" },
      { name: "Baseball", price: "$9.99", category: "Sporting Goods" },
      { name: "Basketball", price: "$29.99", category: "Sporting Goods" },
      { name: "Ipod Touch", price: "$99.99", category: "Electronics" },
      { name: "Iphone 5", price: "$399.99", category: "Electronics" },
      { name: "Nexus 7", price: "$199.99", category: "Electronics" }
    ];
    let rows = [];
    let lastCategory = null;
    items.forEach((item, index) => {
      if (item.category !== lastCategory) {
        rows.push(<Category category={item.category} key={item.category} />);
      }
      rows.push(
        <Row name={item.name} price={item.price} key={"item" + index} />
      );
      lastCategory = item.category;
    });
    return (
      <div>
        <form>
          <input type="text" placeholder="Search..." />
          <p> <input type="checkbox" /> Only show products in stock  </p>
        </form>
        <table>
          <thead>
            <tr>
              <th>Name</th>
              <th>Price</th>
            </tr>
          </thead>
          <tbody> {rows} </tbody>
        </table>
      </div>
    );
  }
});
ReactDOM.render(<MyApp />, document.getElementById("root"));

Hopefully, this has gotten our feet wet into the exciting world of React! React covers a lot more than what I can mention in this tutorial, but with what we've learned in this tutorial, it's more than enough for designers to start building Components in React.

To learn more about React, visit the Documentation and go through the links on the sidebar.

Go create some React Components!!

Discover and read more posts from Oyeniyi Abiola
get started
Enjoy this post?

Leave a like and comment for Oyeniyi

13
1
1Reply
Ian Wang
7 days ago

Thanks for the post! Just one question:
Since you’re using ES6, why do you choose to use createReactClass instead of something like class MyApp extends React.Component?

Get curated posts in your inbox

Read more posts to become a better developer