How to Create React App?

By | March 16, 2022
How to Create React App

React or ReactJS is a JavaScript library, and it is important to note that it is not a framework, like Angular. The main highlight of React is its reusable components that allow faster development as you can easily use a React component several times within a single app as well as across different apps.

If you create a reusable component for an app, then you can just copy-paste it into a different react application, and it will work. This is something that not every JavaScript library or framework has to offer.

React was originally created by developers at Facebook for internal use. However, it is now an open-source JS library maintained by Facebook along with several independent developers and tech companies. Also, the React team runs a blog that provides information about new releases and updates of the React library.

If you are a JavaScript developer and interested in working with React, you have landed just at the right place. In this article, we will guide you to create a React app that will help you strengthen your knowledge of this JS library. Also, we are considering that you have a basic knowledge of React to get started with the project mentioned ahead.

How to Create a React App?

Before your start working on the development of the React app, you need to accomplish certain key tasks that are as follows:

Choose an Integrated Development Environment

We need an IDE to create a React app. There are several IDEs available in the market, but the two most common and frequently used IDEs are WebStorm and Microsoft Visual Studio Code:

a. WebStorm

Vamware

WebStorm is a popular IDE that comes with IntelliSense and other great features. It is developed by JetBrains and offers a free trial for 30 days.

b.Microsoft Visual Studio Code

Vamware

Developed by Microsoft, Visual Studio Code is free to use. It comes with several essential features, like auto code completion, syntax highlighting, and built-in debugging support. It is a lightweight tool having detailed documentation and gets regular updates.

Install Node Package Manager

After downloading and installing the IDE, we need to install the latest Node.js and node package manager (npm). NPM is the online repository that contains open-source Node.js projects. It provides a way for developers to install packages both globally and locally on their systems.

How to Verify Installation of npm?

To check if npm is installed successfully, follow these steps:

  • Run command prompt (or terminal) with administrator privileges.
  • Type node -v and hit enter to check if Node.js is available on your system.
  • Type npm -v and hit enter. If npm is installed, then the version of npm will appear. On the other hand, if it is not installed, you will see a message on the command prompt or terminal interface which says ‘unrecognizable command’.

Access npx

npx is a CLI tool that installs and manages dependencies hosted in the npm publications. After npm version 5.2.0, npx is coming as pre-bundled with npm. We will be using npx to create a React app. You can use the npx -v command to check if npx is installed on your machine or not.

Vamware

Getting Started

npx always creates React apps with the latest dependencies. We can create React apps with npm also but it is always recommended to use npx. Follow these steps to create your first React app.

1. Open your IDE (We’ll be guiding you considering that you have installed the VS Code).

2. Press Ctrl + ~ to open the terminal window.

3. Enter the following command to create a React app:

npx create-react-app space-X

Here space-X is the name of the app and create-react-app is the built-in command. You can provide any name of the app that you want.

It might prompt you to install packages. Press y and hit enter.

C:\Users\paritoshlouhan>npx create-react-app space-X

Need to install the following packages:

  create-react-app

Ok to proceed? (y)

You can also use npm or yarn commands to create a React app:

npm init react-app space-X
yarn create react-app space-X

4. When the app is created successfully, we will navigate to the react app directory (which is space-X in this case) and start the app.

cd space-X

npm start

5. Now you can open any browser, and hit the URL http://localhost:3000/ to see the app running. The default port where your application is hosted locally on your machine is mentioned in the package.json file. Also, It’s always port 3000 unless changed. You can change this port by changing/adding the below-mentioned set of code in the package.json file.

"scripts": {
    "start": “PORT=8000 react-scripts start",
    "build": "react-scripts build"
  }

Creating Components

Components are the smallest logical unit on a page. For eg, if you browse https://jsfiddle.net/, you can see that there are 4 sections of the website, i.e. HTML, CSS, JS, and Result. Apart from these, there is the header and a left pane. Each of these blocks is a component.

From here onwards, we will be working on creating a Space-X app, which filters the Space-X missions based on launch years. This app also supports server rendering of its components with Next.js. The complete working app is available at the following address:

https://space-xprogram.herokuapp.com/

Following are the different components for the Space-X app:

  1. Mission Container – This will contain the details of all the missions along with the heading.
  2. Mission – This will contain details of a single mission.
  3. Filter Container – This will contain all filtering buttons
  4. Filter button – This will contain a single filter button

When you create a component, React will create some sets of files for you. This includes a CSS file, one test file, and one .tsx file. The CLI command to create a component is provided below. I have created a component mission.

npx generate-react-cli component mission

Types of React components

React components are divided into four types that are as follows:

a. Functional component

It is a basic JavaScript function that takes props and returns JSX. It has fewer features as we cannot save states inside this component. Functional components are static and they are used to display anything as it is. Here’s an example:

function Mission() {

  return <span>Hi, I am a spacex mission!</span>;

}

export default HelloWorld;

//To render this, we need to write this
ReactDOM.render(<Mission />, document.getElementById('root'));

b. Class component

It has all the features of the functional components along with many additional functionalities. In the class component, we get leverage to do the following:

  • We can declare states of objects.
  • We can use props to pass values among components.
  • We can change the state of objects in lifecycle methods. The method to create class components is as follows:
class FilterButton extends Component {
    constructor () {
        super()        
        this.handleClick = this.handleClick.bind(this);
    }

    handleClick () {
        this.props.parentCallBack(this.props.value)
    }

    render() {
        return (
            <div className={this.props.className}>
                <button onClick = {this.handleClick}>{this.props.value}</button>
            </div>
        );
    }
}

export default FilterButton;

We have created a filter button class component that contains event handling of a button click and an action to be executed on a button click.

c. Pure components (Advanced)

In React, whenever the object’s state changes, the component re-renders itself. This usually is one of the drawbacks of React. To resolve this, instead of using any of the functional/class components, we can use pure components.

Pure components do not re-render themselves when the value of state and props changes. An example of pure component’s implementation is as follows:

export default class MissionContainer extends React.PureComponent{

   render(){

      return <h1>This is spaceX mission container</h1>;

   }

}

d. Higher-order components (Advanced)

Higher-order components receive data and return values according to that data. It is a JavaScript function that takes one component and returns another component. These components are used to share logic with other components.

Creating events

Events are the actions that happen with DOM elements. There are basically three methods for event binding in React that are as follows:

1. Simple Binding

This binding is by using Arrow functions. Although, this is not the recommended method because a different callback will be created each time EventBind renders. A snippet of its implementation is as follows:

<button onClick = {() => this.clickHandler()}>Click</button>

2. Binding using bind()

In the .bind() method, we can pass in the context to bind to the handler, but it will not immediately run the function. Instead, a copy of that function with the switched context is returned. This copied method will run whenever a user will click on the button. An example of its implementation is provided below:

<button onClick = {this.clickHandler.bind(this)}>Click</button>

//Handler
clickHandler () {
    this.setState({
        message: 'Hello world'
      })
  }

3. Binding with constructor

In binding with a constructor, the click handler is initialized in the constructor. The example of its implementation is shown below:

constructor () {
  super()
  this.state = {
            message : 'Welcome'
         }

  this.clickHandler = this.clickHandler.bind(this);
 }

 clickHandler () {
    this.setState({
        message: 'To the spaceX mission'
      })
  }

  render () {
   return (
    <div>
      <h1>{this.state.message}</h1>
       <button onClick = {this.clickHandler}>Binded</button>
}

Fetching data from API

In React, we can fetch data from any API and categorize that data based on our requirements. Many AJAX libraries can be used with React to fetch the data. For example, we can use Axios, jQuery, or JavaScript’s xhr functions.

The best approach to fetch data with React is by using the Fetch API. The Fetch API provides a JavaScript interface for accessing and manipulating parts of the HTTP pipeline, such as requests and responses.

Benefits of using fetch()

  • fetch() always returns a promise.
  • fetch() never sends cross-origin cookies.
  • According to Google Developers Documentation, fetch() makes it easier to make asynchronous requests and handle responses better than the older XMLHttpRequest.

Before going towards the implementation, we should always remember to fetch and populate data in the componentDidMount lifecycle method only. This helps to use setState to update the components when the data is received. A snippet of code is given below:

componentDidMount() {
    fetch("https://api.spaceXdata.com/v3/launches?limit=100")
    .then(x => x.json())
    .then((launchData) => {
      var launchYears = this.getLaunchYears(launchData)       
      this.setState({
        allLaunch : launchData,
        launchYears: launchYears,
        selectedYearData: launchData
      })
    }
  )
}

The URL to fetch data is to be put inside the fetch function. We can further use then() to convert the promise object into JSON. The moment we call the setState method and assign fetched data to variables, the components will re-render with the received data.

Project Links

Codebase

FilterButton.js
import React, { Component } from 'react';
class FilterButton extends Component {
    constructor () {
        super()        
        this.handleClick = this.handleClick.bind(this);
        this.state = ({
            className : ''
        })
    }

    handleClick () {
        this.props.parentCallBack(this.props.actualValue)        
        let className = this.state.className;
        className =  'selected' + Math.random()
        this.setState({className})
    }
    render() {
        return (
            <div className={this.props.className}>
                <button className={this.state.className} onClick = {this.handleClick}>{this.props.value}</button>
            </div>
        );
    }
}
export default FilterButton;
FiltersContainer.js
import React, { Component } from 'react';
import FilterButton from './FilterButton';
import * as ConstantsFile from '../Constants'

class FiltersContainer extends Component {
    //Created a hardcoded filtering state in boolArray
    constructor () {
        super()
        this.boolArray = [true, false]
        this.state = {
            filterSelectedYearData: []
        }
        this.selectedFilters = []
    }

    //Creating a data store to contain currently selected filters
    addRemoveFilterSelection(filter, moduleName) {
        var currentFilterSelection = {moduleName : moduleName, filter: filter}
        var isSelectedFilterAlreadyPresent = this.selectedFilters.filter(filterObject => (filterObject.moduleName == moduleName && filterObject.filter == filter))
        var isDifferentFilterOfSameModule = this.selectedFilters.filter(filterObject => (filterObject.moduleName == moduleName && filterObject.filter != filter))
        if(isSelectedFilterAlreadyPresent.length > 0){
            var removeIndex = this.selectedFilters.map(filterObject => (filterObject.moduleName)).indexOf(currentFilterSelection.moduleName)
            this.selectedFilters.splice(removeIndex, 1);
        }

        else if(isDifferentFilterOfSameModule.length > 0) {
            var removeIndex = this.selectedFilters.map(filterObject => (filterObject.moduleName)).indexOf(currentFilterSelection.moduleName)
            this.selectedFilters.splice(removeIndex, 1);
            this.selectedFilters.push(currentFilterSelection)
        }
        else {
            this.selectedFilters.push(currentFilterSelection)
        }
    }
    
    //Common method that will be called after user clicks on any filter type
    //This method will callback the parent
    afterFiltering() {
        this.props.parentCallBack(this.state.filterSelectedYearData)
        this.setStyling()
    }

    //Setting selected classes from section wise filtering
    setStyling() {
        if(this.selectedFilters.length > 0) {
            for(var i = 0; i< this.selectedFilters.length ; i++){
                var filterType = this.selectedFilters[i].filter

                switch(this.selectedFilters[i].moduleName) {
                    case ConstantsFile.FILTER_SELECTION_TYPE_Year : 
                    var elems = document.querySelectorAll(".launch-year");  
                    break
                    case ConstantsFile.FILTER_SELECTION_TYPE_LAUNCHING : 
                    var elems = document.querySelectorAll(".launch");
                    break
                    case ConstantsFile.FILTER_SELECTION_TYPE_LANDING : 
                    var elems = document.querySelectorAll(".landing");
                    break
                }
                this.removeSelectedClassFromAllChildComponents(elems, filterType, true)
            }
        }

        else {
            var elemsAllSection = document.querySelectorAll(".launch-year, .launch, .landing");
            this.removeSelectedClassFromAllChildComponents(elemsAllSection, null, false)
        }
    }

    //Removing unnecessary classs on DOM
    removeSelectedClassFromAllChildComponents (elems, filterType, clearSection) {
        if(clearSection) {
            [].forEach.call(elems, function(el) {
                if(el.innerText.toLowerCase().toString() != filterType.toString()) {
                    el.children[0].classList = '';
                }
            });    
        }

        else {
            [].forEach.call(elems, function(el) {
                el.children[0].classList = '';
            });
        }
    }

    //Rendering complete data
    renderSetState(filteredrocketsList) {
        this.setState({
            filterSelectedYearData : filteredrocketsList
        }, () => {
            this.afterFiltering()
        }); 
    }

    //Callback method if user clicked on any year button
    //This method will filter all missions of particular year on which user has clicked
    filterSelectedYearData = (selectedYear) => {
        this.addRemoveFilterSelection(selectedYear, ConstantsFile.FILTER_SELECTION_TYPE_Year)
        this.renderCompleteFilteredData()
    }

    //Callback method if user clicked on any Launch type button
    //This method will filter all missions of particular launch on which user has clicked
    filterSelectedLaunchType = (selectedType) => {
        this.addRemoveFilterSelection(selectedType, ConstantsFile.FILTER_SELECTION_TYPE_LAUNCHING)
        this.renderCompleteFilteredData()
    }

    //Callback method if user clicked on any Land type button
    //This method will filter all missions of particular land on which user has clicked
    filterSelectedLandingType = (selectedType) => {
        this.addRemoveFilterSelection(selectedType, ConstantsFile.FILTER_SELECTION_TYPE_LANDING)
        this.renderCompleteFilteredData()
    }

    renderCompleteFilteredData () {
        var filteredrocketsList =this.props.state.allLaunch, filteredrockets;
        for(var i = 0; i< this.selectedFilters.length ; i++){
            switch(this.selectedFilters[i].moduleName) {
                case ConstantsFile.FILTER_SELECTION_TYPE_Year : 
                filteredrockets = filteredrocketsList.filter((rocket) => {return rocket.launch_year == this.selectedFilters[i].filter})
                break
                case ConstantsFile.FILTER_SELECTION_TYPE_LAUNCHING : 
                filteredrockets = filteredrocketsList.filter((rocket) => {return rocket.launch_success == this.selectedFilters[i].filter})
                break
                case ConstantsFile.FILTER_SELECTION_TYPE_LANDING : 
                filteredrockets = filteredrocketsList.filter((rocket) => {return rocket.rocket.first_stage.cores[0].land_success == this.selectedFilters[i].filter})
                break
            }
            filteredrocketsList = filteredrockets
        }
        this.renderSetState(filteredrocketsList)
    }
    
    //Method will render all years button component
    renderLaunchYearComponent () {
        var launchYearsComponents=[];
        var numberOfButtons = this.props.state ? this.props.state.launchYears.length : 0
        for(var i=0; i < numberOfButtons; i++){
          if(this.selectedFilters.filter(filter => (filter.filter == filter)))
          launchYearsComponents.push(
          <FilterButton 
          key={i} 
          actualValue={ this.props.state.launchYears[i] } 
          value={ this.props.state.launchYears[i] } 
          parentCallBack = {this.filterSelectedYearData}
          className = 'launch-year' />);
        }
        return launchYearsComponents;
    }

    //Method will render successful Launch button components
    renderSuccessfulLaunchComponent () {
        var launchComponent=[];
        var boolStringArray = [ConstantsFile.TRUE, ConstantsFile.FALSE]
        for(var i=0; i<this.boolArray.length; i++){
        launchComponent.push(
          <FilterButton 
          key={i}
          actualValue = {this.boolArray[i]} 
          value={ boolStringArray[i] } 
          parentCallBack = {this.filterSelectedLaunchType}  
          className = 'launch'/>);
        }
        return launchComponent;
    }

    //Method will render successful Land button components    
    renderSuccessfulLandingComponent () {
        var landingComponent=[];
        var boolStringArray = [ConstantsFile.TRUE, ConstantsFile.FALSE]
        for(var i=0; i< this.boolArray.length; i++){
        landingComponent.push(
          <FilterButton 
          key={i} 
          actualValue = {this.boolArray[i]}
          value={ boolStringArray[i] } 
          parentCallBack = {this.filterSelectedLandingType} 
          className = 'landing'/>);
        }
        return landingComponent;
    }

    //Removing all filters from the page
    removeAllFilters = () => {
        this.selectedFilters = []        
        this.setState({
            filterSelectedYearData : this.props.state.allLaunch
        }, () => {
            this.afterFiltering()
        })
    }

    render() {
        var launchYearsComponents = this.renderLaunchYearComponent();
        var successfulLaunchComponent = this.renderSuccessfulLaunchComponent();
        var successfulLandingComponent = this.renderSuccessfulLandingComponent();
        var totalCount = this.state.filterSelectedYearData.length == 100 ? 0 : this.state.filterSelectedYearData.length

        return (
            <div className = 'filter-container'>
                <heading className = 'filter-container-heading'>Filters</heading> 
                <a className = 'refresh-all' href="#" onClick={this.removeAllFilters}>Reset filters</a>
                <label className='heading'>Launch Year</label>
                {launchYearsComponents}
                <label className='heading'>Successful Launch</label>
                {successfulLaunchComponent}
                <label className='heading'>Successful Landing</label>
                {successfulLandingComponent}
                <label className="filter-count">Total Filter Result Count :  </label><label>{" " +totalCount}</label>
            </div>
        );
    }
}

export default FiltersContainer;
Mission.js
import React, { Component } from 'react';
import * as ConstantsFile from '../Constants'

class Mission extends Component {
    //Converting the list into a string
    getMissionIdsList () {
        var idsList = ""
        var missionIdsLength = this.props.value ? this.props.value.mission_id.length : 0        
        if(missionIdsLength > 0) {
            for(var i=0; i < missionIdsLength; i++) {
                idsList +=  " " +this.props.value.mission_id[i]
            }    
        }

        else {
            idsList = ConstantsFile.NO_ID
        }
        return idsList
    }

    render() {
        //Check implementation if no data is received in api response
        var landValue;

        if(this.props.value)
        {
            var launchValue = this.props.value.launch_success == true ? ConstantsFile.TRUE : ConstantsFile.FALSE

            if(this.props.value.rocket.first_stage.cores[0].land_success == true) {
                landValue = ConstantsFile.TRUE
            }

            else if(this.props.value.rocket.first_stage.cores[0].land_success == false) {
                landValue = ConstantsFile.FALSE
            }

            else {
                landValue = ConstantsFile.NULL
            }

            var idsList = this.getMissionIdsList()
            var imageLink = this.props.value.links.mission_patch_small
            var missionName = this.props.value.mission_name 
            var launchYear = this.props.value.launch_year 

            return (
                <div className = 'mission'>
                    <img src={imageLink} alt='spaceX Logo'></img>
                    <header className='mission-name'>{missionName}</header>
                    <label className='text'>Mission ids: </label> 
                    <label className='value'>{idsList}</label>
                    <label className='text'>Launch Year : </label>
                    <label className='value'>{launchYear}</label>
                    <label className='text'>Successful Launch : </label> 
                    <label className='value'>{launchValue}</label>
                    <label className='text'>Successful Land : </label> 
                    <label className='value'>{landValue}</label>
                </div>
            );  
        }

        else {
            return <label>No Data received!</label>
        }
        
    }
}

export default Mission;
MissionsContainer.js
import React, { Component } from 'react';

import Mission from './Mission'

class MissionsContainer extends Component {
    renderMissionComponent () {
        var missionComponent=[];

        if(this.props.state && this.props.state.filteredData) {
            var numberOfAllMissionCount = this.props.state ? this.props.state.allLaunch.length : 0
            var numberOfFilteredMissionCount = this.props.state ? this.props.state.filteredData.length : 0    
        }

        //Rendering Missions after user click buttons of filter type 
        if(numberOfFilteredMissionCount > 0 && this.props.state) {
            for(let i=0; i< numberOfFilteredMissionCount; i++){
                missionComponent.push(
                  <Mission 
                  key={i} 
                  value={ this.props.state.filteredData[i] }  />);
                }        
        }

        else {
            //Rendering all missions
            for(let i=0; i< numberOfAllMissionCount; i++){
                missionComponent.push(
                  <Mission 
                  key={i} 
                  value={ this.props.state.allLaunch[i] }  />);
                }        
        }
        return missionComponent;
    }

    render() {
        var launchMissionComponents = this.renderMissionComponent();
        if(this.props.state && this.props.state.filteredData && this.props.state.filteredData.length == 0) {
            return (
                <div className = 'mission-container'>
                    <h3 className="no-data">Data is being fetched... Or, there is no data matching your filters. Please try again!</h3>
                </div>
            );         
        }

        else {

            return (
                <div className = 'mission-container'>
                    {launchMissionComponents}
                </div>
            );    
        }     
    }
}

export default MissionsContainer;
index.js
import react, {Component} from 'react'
import FiltersContainer from './FilterComponents/FiltersContainer'
import MissionsContainer from './FilteredDataDisplayComponents/MissionsContainer' 
import * as ConstantsFile from './Constants'

class App extends Component {
    constructor () {
    super()

    // Creating a state that will be filled with the data fetched
    // from API
    this.state = {
      allLaunch : [],
      launchYears: [],
      filteredData: []
    }
  }

  //Method that will retrieve and return the numbers of distinct years of SpaceX mission
  getLaunchYears (launchData) {
    let rockets = launchData.map((rocket) => rocket.launch_year)
    var launchYears = [];

    rockets.forEach((rocket) => {
      if(!launchYears.includes(rocket)){
       launchYears.push(rocket)
      }
    })
    return launchYears
  }

  //Callback method received from child component.
  //It will set state of number of rockets sent on a year user has clicked
  filterSelectionReceived = (filteredrocketsListObject) => {
    this.setState({
      filteredData: filteredrocketsListObject,
    })
  }

  componentDidMount() {
    fetch(ConstantsFile.API)
    .then(x => x.json())
    .then((launchData) => {
      var launchYears = this.getLaunchYears(launchData)       

      this.setState({
        allLaunch : launchData,
        launchYears: launchYears,
        filteredData:launchData
      })
    }
  )
}  

render() {

   return (
    <div className="App">
      <header>SpaceX Launch Programs</header>
      <FiltersContainer state = {this.state} parentCallBack = {this.filterSelectionReceived}/>
      <MissionsContainer state = {this.state}/>
      <footer>Developed by Paritosh Louhan</footer>

    </div>
    );
  }
}

export default App;
Constants.js
export const API = "https://api.spaceXdata.com/v3/launches?limit=100"
export const FILTER_SELECTION_TYPE_Year = 'Year';
export const FILTER_SELECTION_TYPE_LAUNCHING = 'Launching';
export const FILTER_SELECTION_TYPE_LANDING = 'Landing';
export const TRUE = 'True';
export const FALSE = 'False';
export const NULL = 'NULL';
export const NO_ID = 'No ID Found';

export default constant => {
    return "";
}

Conclusion

This article will help you to create a basic React app using an API. Also, the project makes use of various React features, such as components, props, event handling, fetch calls, and lifecycle hooks. To enhance your knowledge further, you still need to cover up topics like redux, virtual DOM, JSX, and advanced event handling to have a better grip on React.

Furthermore, when your app is ready, you can hit F12 in the chrome browser and go to the Lighthouse tab. Generate reports and Chrome will assess your application based on performance, accessibility, best practices, and SEO. It will also provide you with the steps to improve the performance of your application. You can show off your light score in any coding assessment and it will add a feather to your cap.

If you like this article or want to contribute knowledge to this article, then please let us know in the comment section below.

People are also reading: 

Author: Paritosh Louhan

Paritosh is a developer by profession and a writer by heart. He is working with Nagarro as a Team Lead and loves to write in his free time. He believes that anything that couldn’t be achieved by training can be accomplished by a strong will. Will to act!

Leave a Reply

Your email address will not be published.