How to Create React App?

Posted in /  

How to Create React App?
paritoshlouhan

Paritosh Louhan
Last updated on March 28, 2024

    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 to 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 : 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 : 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.

    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 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 a 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 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:

    FAQs


    React is a JavaScript-based library for creating user interfaces for websites based on UI components.

    A Node Package Manager (npm) is the world's largest software registry for JavaScript, containing over 800,000 code packages.

    The four different types of React components are: 1. Functional components 2. Class components 3. Pure components 4. High-order components.

    Leave a Comment on this Post

    0 Comments