Create a basic ReactJS app with no config


There are many ways that a ReactJs app can be created. The aim of this guide is to get up and running with a basic react app as quickly as possible.

That means no other fancy libraries such as Redux, Router, Relay or anything else beginning with R (seems like there is a theme going on). There’s also going to be no Flux or jQuery or any other async included and certainly no configuration needed via WebPack, Babel or Gulp.

How do we get started so easily… Thankfully there is Facebook’s Create React App. These first step, taken from the CRA will get a new project up and running with no config. It’s from there that we can start to play with React.

First we need to install the tool (You’ll need Node/npm installed beforehand) then we move into the directory and start the app. Mine is called react-01 but you can call it what you want! Open up a terminal window:

npm install -g create-react-app
create-react-app react-01
cd react-01/
npm start

And now you’ll see a basic page with a spinning React logo and some starter instructions “To get started, edit src/App.js and save to reload.”, so let’s do that.

Open up src/App.js and let’s have a look at making our own components.

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
class App extends Component {
  render() {
    return (
      <div className="App">
        <div className="App-header">
          <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;

By default it comes with a bit of extra code that we can get rid of. This may be useful later once you start adding styles and images, but for now let’s start from fresh.

Replace the whole file contents with:

import React, { Component } from 'react';
class App extends Component {
  render() {
    return (
      <div>
        <h1>Hello React!</h1>
      </div>
    );
  }
}

export default App;

Save and Voila! You have done your first bit of React. It’s written in JSX too, so you can tick that box also! Let’s not stop there though, we’ve only scratched the surface. We need components. Components can be used just like HTML tags, we just need to define them first before we use them.

Let’s make one now. Add a List component after the import React and before the App component:

import React, { Component } from 'react';

class List extends Component {
}

class App extends Component {
  render() {
    return (
      <div>
        <h1>Hello React!</h1>
        <List />
      </div>
    );
  }
}
export default App;

When you save and the page reloads… Nothing… that’s because a component must have a render function to display it’s HTML. The render function can optionally have some logic in it to show and hide content depending on variables but in it’s simplest form it just needs to return some HTML. Please note that from here on in, I’ll mostly be sharing snippets of code and not the whole files each time. Hopefully you can follow along!

class List extends Component {
  render() {
    return (
      <h2>List title</h2>
    )
  }
}

Now, a list is not very good if it doesn’t have any contents so lets start by adding a

    to contain the elements

    class List extends Component {
      render() {
        return (
          <h2>List title</h2>
          <ul>
          
          </ul>
        )
      }
    }
    

    OOPS! Now we have an error. This is because a render function should only ever return one root element. A component can be as complicated as you want inside, but due to the way the DOM is built by the JavaScript it can only ever handle one element at the outer most level of a component. Let’s fix that by wrapping both components in a single

    class List extends Component {
      render() {
        return (
          <div>
            <h2>List title</h2>
            <ul>
            
            </ul>
          </div>
        )
      }
    }
    

    Now let’s make a new component for the ListItems and then put 3 of them in the List component’s

      class ListItem extends Component {
        render() {
          return (
            <li>Item</li>
          )
        }
      }
      
      class List extends Component {
        render() {
          return (
            <div>
              <h2>List title</h2>
              <ul>
                <ListItem />
                <ListItem />
                <ListItem />
              </ul>
            </div>
          )
        }
      }
      

      Now we have a basic list, but it’s a bit useless since it’s all static content. We should really populate it from some data. In the real world the data could come from an API, but to keep things simple let’s just add it as a variable for now. Add a variable just after the first line:

      import React, { Component } from 'react';
      let list_data = [
        "Cat",
        "Dog",
        "Fish",
        "Parrot",
        "Rabbit"
      ]
      ...
      

      Remember when I said we could use some logic in the render function, well now we can. In the List component we need to add add a variable that returns the array of data mapped to the ListItems. Then we render the variable to the HTML

      class List extends Component {
        render() {
      // Create variable with mapped data
          let list_items = list_data.map(function(item, index) {
            return (
              <ListItem />
            )
          })
      // Return the HTML
          return (
            <div>
              <h2>List title</h2>
              <ul>
                {list_items}
              </ul>
            </div>
          )
        }
      }
      

      When we create the variable from the data array we map each element in the array and pass it to a function. The inner function returns the HTML for that item. We can then use the variable in the returned HTML.

      Variables in react templates are wrapped in {}. You can also put logic in the brackets, but that can end up looking messy if you have too much in there. I prefer to keep the logic out of the render return as much as I can.

      Anyway you should now notice 5 Items (if you used my data array). You will also notice that that they still just say “Item” which is not really that cool. Let’s fix that!

      First let’s pass the item text to the ListItem. Note that the item variable (which is an object from the data_list array) is being passed to the ListItem as a Prop called “text”:

      class List extends Component {
        render() {
      // Create variable with mapped data
          let list_items = list_data.map(function(item, index) {
            return (
              <ListItem text={item} />
            )
          })
      // Return the HTML
         ...
      

      Now let’s update our ListItem to display it’s newly acquired Prop.

      class ListItem extends Component {
        render() {
          return (
            <li>{this.props.text}</li>
          )
        }
      }
      

      All good? Well actually no. One of the things that makes react so great is how it updates the UI so quickly and seamlessly. It does most of this using magic, but it does need our help understanding which elements are new, have changes or have been removed. If you open up the browser console you should see an error stating:

      Warning: Each child in an array or iterator should have a unique “key” prop. Check the render method of List

      That is because React doesn’t know which elements are which. It’ll still render them to the page, but it won’t do it efficiently and that’s bad.

      We must help react by giving each element that is mapped a unique key. If we were getting our data from a database/API we could use the id of the item from there. Since we have an array and our map function returns an index we can use that. We should use a unique property for the key. Don't use an index. It's bad for render performance.

      ...
      // Create variable with mapped data
          let list_items = list_data.map(function(item) {
            return (
              <ListItem text={item} key={item} />
            )
          })
      ...
      

      It was that easy. Looks like nothing changed. It’s now that you should look at getting the React Developer Tools for your browser… Do that now. I’ll wait…

      Now back in the browser you should see a react tab in the developer tools panel. Before you click it inspect one of your items as normal.

      Then checkout the React tab. See how the React tab shows your component structure and the keys. Have a click around and compare it to the HTML markup.

      So now that we have a set of nested components and some data being displayed it’s time to do some housekeeping. If this was a real app and all the Components were in one file that would be a nightmare, not to mention that if we make components in a modular way then we can use them in multiple apps.

      Here’s what you should have so far:

      import React, { Component } from 'react';
      let list_data = [
        "Cat",
        "Dog",
        "Fish",
        "Parrot",
        "Rabbit"
      ];
      
      class ListItem extends Component {
        render() {
          return (
            <li>{this.props.text}</li>
          )
        }
      }
      
      class List extends Component {
        render() {
      // Create variable with mapped data
          let list_items = list_data.map(function(item, index) {
            return (
              <ListItem text={item} key={index} />
            )
          })
      // Return the HTML
          return (
            <div>
              <h2>List title</h2>
              <ul>
                {list_items}
              </ul>
            </div>
          )
        }
      }
      
      class App extends Component {
        render() {
          return (
            <div>
              <h1>Hello React!</h1>
              <List />
            </div>
          );
        }
      }
      
      export default App;
      

      Making the app modular

      Let’s start to make the app more modular. First though, lets add a second list to see why we should do things in a modular way.

      class App extends Component {
        render() {
          return (
            <div>
              <h1>List of lists</h1>
              <h2>Top animals</h2>
              <List />
              <h2>Other animals</h2>
              <List />
            </div>
          );
        }
      }
      

      At this point we have 2 lists with the content being the same. We could make another list component, but what if we have a third or fourth list to display (I really like lists). We could instead use Props again and pass the list data to the component. Make a new array of animals named otheranimals and while we’re at it let’s rename the first list to topanimals

      let top_animals = [
        "Cat",
        "Dog",
        "Fish",
        "Parrot",
        "Rabbit"
      ]
      let other_animals = [
        "koala",
        "Chimp",
        "Tiger",
        "Shark",
        "Humming bird"
      ]
      

      Then in the App component let’s pass a prop to each List with the data they should display

      class App extends Component {
        render() {
          return (
            <div>
              <h1>List of lists</h1>
              <h2>Top animals</h2>
              <List data={top_animals} />
              <h2>Other animals</h2>
              <List data={other_animals} />
            </div>
          );
        }
      }
      

      Then finally in the List component we need to update the mapping function to use the new data from the prop instead of the old hardcoded array variable:

      // Create variable with mapped data
          let list_items = this.props.data.map(function(item) {
            return (
              <ListItem text={item} key={item} />
            )
          })
      

      And there you have it. Multiple lists. Feel free to add some more data arrays and List components.

      Housekeeping and better practices

      The next step is to make the components their own files. Create a new file in the src folder components/List.js then cut the List component from the App.js file into it. At the top of that file add the react import so you end up with:

      import React, { Component } from 'react';
      class List extends Component {
        render() {
      // Create variable with mapped data
          let list_items = this.props.data.map(function(item, index) {
            return (
              <ListItem text={item} key={index} />
            )
          })
      // Return the HTML
          return (
            <div>
              <h3>List title</h3>
              <ul>
                {list_items}
              </ul>
            </div>
          )
        }
      }
      

      Do the same with the ListItem code so you end up with a file named src/components/ListItem.js containing:

      import React, { Component } from 'react';
      class ListItem extends Component {
        render() {
          return (
            <li>{this.props.text}</li>
          )
        }
      }
      

      Then in the App.js file we need to import the List component so it can be used.

      import React, { Component } from 'react';
      import List from './components/List';
      ...
      

      Do the same in the List.js file so that it can use the ListItem:

      import React, { Component } from 'react';
      import ListItem from './ListItem';
      ...
      

      The final thing we need to do is (export)[http://stackoverflow.com/questions/21117160/what-is-export-default-in-javascript] each component from it’s file so that it can be imported by others.

      Right at the end of List.js file add the following line:

      export default List;
      

      and at the end of ListItem.js file add:

      export default ListItem;
      

      Now all that remains is a little more tidying. Since our list has a few requirements to make it work we should define some PropTypes to help us with error checking (e.g. A component that expects an array of Strings will complain if it gets an Int). It’s a bit more work but it’s a good practice that will end up saving you some headaches when you have forgotten how the component works in 6 months.

      Let’s start with the ListItem since it’s the simplest.

      import React, { Component } from 'react';
      import PropTypes from 'prop-types';
      class ListItem extends Component {
        render() {
          return (
            <li>{this.props.text}</li>
          )
        }
      }
      ListItem.propTypes = {
        text: PropTypes.string.isRequired
      };
      export default ListItem;
      

      We have set the text prop type to be a string. That means if we pass anything other than a string to the ListItem for the text properly there will be an error logged in the console. Try updating one of the lists with some other values

      let other_animals = [
        "koala",
        "Chimp",
        "Tiger",
        "Shark",
        "Humming bird",
        null,
        false,
        1
      ]
      

      An error caused by a null value:

      warning.js:36 Warning: Failed prop type: The prop text is marked as required in ListItem, but its value is null.

      An error caused by the wrong type of value

      warning.js:36 Warning: Failed prop type: Invalid prop text of type boolean supplied to ListItem, expected string.

      It will still render the list, but when you are debugging something later on it’s good to know if you are passing the right values around. Undo that breaking code by removing the null, false and Int values!

      Now let’s update the List component. We also need to add a title to it as a property so it’s properly reusable.

      import React, { Component } from 'react';
      import PropTypes from 'prop-types';
      import ListItem from './ListItem';
      class List extends Component {
        render() {
      // Create variable with mapped data
          let list_items = this.props.data.map(function(item, index) {
            return (
              <ListItem text={item} key={index} />
            )
          })
      // Return the HTML
          return (
            <div>
              <h3>{this.props.title}</h3>
              <ul>
                {list_items}
              </ul>
            </div>
          )
        }
      }
      List.propTypes = {
        title: PropTypes.string.isRequired,
        data: PropTypes.arrayOf(PropTypes.string).isRequired
      };
      export default List;
      

      PropTypes can be nested so we can require an array with string values inside. There are many other PropTypes depending on what you need. Now we need to pass a title prop to the List component so in the App.js file let’s get that done.

      ...
      class App extends Component {
        render() {
          return (
            <div>
              <h1>List of lists</h1>
              <List data={top_animals} title="Top animals" />
              <List data={other_animals} title="Other animals"/>
            </div>
          );
        }
      }
      ...
      

      And to test our propTypes let’s break it for a moment by updating the other_animals:

      let other_animals = ‘car’;
      

      Failed prop type: Invalid prop data of type string supplied to List, expected an array.

      And you will also see: Uncaught TypeError: this.props.data.map is not a function

      This is because the list .map function is trying to map on something that doesn’t have that function available since strings don’t have .map. From the first warning we can see that we’re supplying the wrong kind of variable and can fix things more easily and quickly.

      Undo that broken code by setting other_animals back to the array of strings!

      So there you have it, you have scratched the surface of React. You have a basic set of nested components that render their (type validated) data. You can (download the final files from GitHub)[https://github.com/Designer023/ReactJS-tutorial-files-01].

      This is my first React tutorial and also first tutorial in a long time, so any feedback is most welcome.