Explore Free React Tutorials – GameDev Academy https://gamedevacademy.org Tutorials on Game Development, Unity, Phaser and HTML5 Sun, 19 Feb 2023 21:14:35 +0000 en-US hourly 1 https://wordpress.org/?v=6.1.1 https://gamedevacademy.org/wp-content/uploads/2015/09/cropped-GDA_logofinal_2015-h70-32x32.png Explore Free React Tutorials – GameDev Academy https://gamedevacademy.org 32 32 How to Submit Forms and Save Data with React and Node https://gamedevacademy.org/how-to-submit-forms-and-save-data-with-react-js-and-node-js/ Sun, 18 Dec 2022 14:24:31 +0000 https://html5hive.org/?p=1228 Read more]]> While there are multiple ways to deal with forms on the web, the popular React library offers a unique and easy way to do it.

In this tutorial, we’re going to explore how to combine React, Node.js, and various techniques to allow users to submit forms – and then save that data so we can use it for whatever backend purposes we might need.

If you’re ready to explore some core web fundamentals, let’s jump into it.

Intro

In my last two tutorials, I covered the basics of React.js and form error handling in React.js. In each case, I used hard-coded data. React is a front-end library, providing no easy way to save to, or read information from, a database or file. That is the part we will cover in this tutorial – but if you need some refreshing on React, especially on Props & States, feel free to read the linked resources.

React is a user interface library, so it is common to use a different library or framework to do all the back-end work. One of the most common pairings is React.js with Node.js. Lucky for us, we already have a tutorial on the basics of Node right here!

The main React Facebook tutorial does something similar to what we will be doing with this tutorial, and they also provide a Node server, as well as many other server examples within their download files. Although our Node server will be similar, our front-end React interface will have a few extra complications. In fact, I’ll be using the same files from my form error handling React tutorial, with a few updates that will allow the saving and reading of information from a file or database.

Download the tutorial files & prerequisites

You can download all the files used in this tutorial from here.

As hinted above, we do assume that you know the fundamentals of web development (especially JavaScript which heavily plays into both Node and React). For those a bit new to these topics – or even just in need of a review – you might want to try some online courses first to make sure you’re ready.

We also don’t recommend React or Node for classroom teaching. Instead, you can check out K12-friendly web development courses on Zenva Schools that will be perfect for the classroom.

BUILD YOUR OWN GAMES

Get 250+ coding courses for

$1

AVAILABLE FOR A LIMITED TIME ONLY

Learn React online

If you are keen to learn React from the ground-up feel free to check Learn and Understand React JS on Zenva Academy which covers all the basics + lots of bonus topics like React Router and Flux.

Tutorial requirements

  • You must have basic knowledge of React.js and JavaScript. For a beginner’s guide to React, please see my past tutorial. In addition, I will be using many of the same functions from my other React tutorial, so you may want to read that one as well.
  • You will need to use the React library, although we will be using CDN links to get around that during testing.
  • You will need to download a text editor of some sort. You can use just a plain text editor, although Notepad++ is popular on Windows, and TextMate is popular on Mac machines. An editor with code highlighting capability is preferable.
  • You will need to read and follow the directions in most of the beginner’s Node.js tutorial in order to create the server that will be used later in this tutorial.

Making revisions to a React user interface

I will be using the same files I created for the error handling tutorial, with some simple revisions that will make it possible to read and save data. The files with all the revisions are provided above. The index file from the previous tutorial remains the same, but now we are going to be pulling data from a file, then posting new form entries to the file.

The original file was set up with some of the code needed to post and read data, but some parts were commented out, since we had no server to do the work. All we have to do is uncomment those lines, and we have this:

var DonationBox = React.createClass({
  getInitialState: function() {
    //this will hold all the data being read and posted to the file
    return {data: []};
  },
  loadDonationsFromServer: function() {
    $.ajax({
      url: this.props.url,
      dataType: 'json',
      cache: false,
      success: function(data) {
        this.setState({data: data});
      }.bind(this),
      error: function(xhr, status, err) {
        console.error(this.props.url, status, err.toString());
      }.bind(this)
    });
  },
  componentDidMount: function() {
    this.loadDonationsFromServer();
    setInterval(this.loadDonationsFromServer, this.props.pollInterval);
  },
  handleDonationSubmit: function(donation) {
    //this is just an example of how you would submit a form
    //you would have to implement something separately on the server
    $.ajax({
      url: this.props.url,
      dataType: 'json',
      type: 'POST',
      data: donation,
      success: function(data) {
        this.setState({data: data});
      }.bind(this),
      error: function(xhr, status, err) {
        console.error(this.props.url, status, err.toString());
      }.bind(this)
    });
  },
  render: function() {
    return (
      <div className="donationBox">
        <h1>Donations</h1>
        <DonationList data={this.state.data} />
        <DonationForm onDonationSubmit={this.handleDonationSubmit} />
      </div>
    );
  }
});

ReactDOM.render(
  <DonationBox url="/api/donations" pollInterval={2000} />,
  document.getElementById('content')
);

So far, everything we have here is similar to Facebook’s Commenting tutorial. We save all the data from the file in a DonationBox component state, then set an interval to pull new donations from the server so the user can see new donations as they come in, in close to real time. On each form submission, the data is pushed to the database (or in this case, the file). We include JQuery in the index file in order to make the loading and submitting of data easier.

Let’s continue with the changes I’ve made to the form before discussing the server side.

Displaying new data from everyone

We now have a new listing that will display all new donations coming from all users.

var DonationList = React.createClass({
  render: function() {
    var donationNodes = this.props.data.map(function(donation) {
      return (
        <Donation
          contributor={donation.contributor}
          key={donation.id}
          amount={donation.amount}
        >
          {donation.comment}
        </Donation>
      );
    });
    return (
      <div className="donationList">
        {donationNodes}
      </div>
    );
  }
});

Similar to the Facebook tutorial, we are mapping out all the data from the JSON file into a new Donation component for each entry. We then display the entire donationNodes list. Let’s take a look at the new Donation component:

var Donation = React.createClass({
  render: function() {
    return (
      <div className="donation">
        <h2 className="donationContributor">
          {this.props.contributor}: ${this.props.amount}
        </h2>
          {this.props.children.toString()}
      </div>
    );
  }
});

This is actually simpler than what we see in the Facebook tutorial, because we are expecting comments by contributors to be in plain text. We are simply displaying the main donation information, leaving out anything private. In fact, we are only saving the public information for the purposes of this tutorial, but it’s easy enough to store all of the data in a database, then only display the information that is public.

So far, our additions are very similar to what you can find in the Facebook tutorial, but our original Donation app is nothing like that tutorial. This is where the changes become a little more complicated.

Submitting form data

In the original donation app, we had some fairly complicated calls to other components that allowed us to serve up multiple fields from a single component. Now that we have to think about actually saving and displaying that data, we have to add a value attribute to the components that will allow us to empty all the fields after submission, and we also have to save all the data in a state.

var DonationForm = React.createClass({
  getInitialState: function() {
    return {
      contributor: "",
      amount: undefined,
      comment: "",
      email: "",
      department: undefined
    };
  },
  handleSubmit: function(e) {
    //we don't want the form to submit, so we prevent the default behavior
    e.preventDefault();
    
    var contributor = this.state.contributor.trim();
    var amount = this.state.amount;
    var comment = this.state.comment.trim();
    if (!contributor || !amount) {
      return;
    }
    
    //Here we do the final submit to the parent component
    this.props.onDonationSubmit({contributor: contributor, amount: amount, comment: comment});
    this.setState({
      contributor: '',
      amount: undefined,
      comment: '',
      email: '',
      department: undefined
    });
  },
  validateEmail: function (value) {
    // regex from http://stackoverflow.com/questions/46155/validate-email-address-in-javascript
    var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
    return re.test(value);
  },
  validateDollars: function (value) {
    //will accept dollar amounts with two digits after the decimal or no decimal
    //will also accept a number with or without a dollar sign
    var regex  = /^\$?[0-9]+(\.[0-9][0-9])?$/;
    return regex.test(value);
  },
  commonValidate: function () {
    //you could do something here that does general validation for any form field
    return true;
  },
  setValue: function (field, event) {
    //If the input fields were directly within this
    //this component, we could use this.refs.[FIELD].value
    //Instead, we want to save the data for when the form is submitted
    var object = {};
    object[field] = event.target.value;
    this.setState(object);
  },
  render: function() {
    //Each form field is actually another component.
    //Two of the form fields use the same component, but with different variables
    return (
      <form className="donationForm" onSubmit={this.handleSubmit}>
        <h2>University Donation</h2>
      
        <TextInput
          value={this.state.email}
          uniqueName="email"
          text="Email Address"
          textArea={false}
          required={true}
          minCharacters={6}
          validate={this.validateEmail}
          onChange={this.setValue.bind(this, 'email')} 
          errorMessage="Email is invalid"
          emptyMessage="Email is required" />
        <br /><br />

        <TextInput
          value={this.state.contributor}
          uniqueName="contributor"
          text="Your Name"
          textArea={false}
          required={true}
          minCharacters={3}
          validate={this.commonValidate}
          onChange={this.setValue.bind(this, 'contributor')} 
          errorMessage="Name is invalid"
          emptyMessage="Name is required" />
        <br /><br />
          
        <TextInput
          value={this.state.comment}
          uniqueName="comment"
          text="Is there anything you'd like to say?"
          textArea={true}
          required={false}
          validate={this.commonValidate}
          onChange={this.setValue.bind(this, 'comment')} 
          errorMessage=""
          emptyMessage="" />
        <br /><br />
      
        {/* This Department component is specialized to include two fields in one */}
        <h4>Where would you like your donation to go?</h4>
        <Department
          value={this.state.department} 
          onChange={this.setValue.bind(this, 'department')} />
        <br /><br />
      
        {/* This Radios component is specialized to include two fields in one */}
        <h4>How much would you like to give?</h4>
        <Radios
          value={this.state.amount}
          values={[10, 25, 50]}
          name="amount"
          addAny={true}
          anyLabel=" Donate a custom amount"
          anyPlaceholder="Amount (0.00)"
          anyValidation={this.validateDollars}
          onChange={this.setValue.bind(this, 'amount')} 
          anyErrorMessage="Amount is not a valid dollar amount"
          itemLabel={' Donate $[VALUE]'} />
        <br /><br />
      
        <h4>Payment Information</h4>
        <Payment />
        <br />
      
        <input type="submit" value="Submit" />
      </form>
    );
  }
});

As you can see, we’ve added new states for each piece of data we plan on saving. The other bits of data can always be added later, but we are just going to focus on the data that we want to display. On submit, we send all the data to the parent component to do the actual saving to the server. We then reset all the fields so they will appear empty after submission.

We also have a new method called setValue. Because we do not have form fields directly within this component, we have to have a way to set the state as we go (using the onChange attribute in each component call). Rather than create a new function for every form field, we use this single function by taking the field as a variable, and using it to create a new object that can be used to set the state for that field. The field name is included in the call to the component.

Each component call also has a new value attribute. This is what allows us to empty all the fields when the form is submitted. I’ve have also added a new text field, with an option for producing a textarea rather than a single line text field. This allows us to add a new comment field for contributors who want to say something about why they’re donating. Now let’s take a look at the few changes made to the form element components.

Emptying fields on form submission

There are no changes to the InputError component, but we do have a few small changes to the other components which will allow us to empty all the fields after submission.

var TextInput = React.createClass({
  getInitialState: function(){
    //most of these variables have to do with handling errors
    return {
      isEmpty: true,
      value: null,
      valid: false,
      errorMessage: "Input is invalid",
      errorVisible: false
    };
  },

  handleChange: function(event){
    //validate the field locally
    this.validation(event.target.value);

    //Call onChange method on the parent component for updating it's state
    //If saving this field for final form submission, it gets passed
    // up to the top component for sending to the server
    if(this.props.onChange) {
      this.props.onChange(event);
    }
  },

  validation: function (value, valid) {
    //The valid variable is optional, and true if not passed in:
    if (typeof valid === 'undefined') {
      valid = true;
    }
    
    var message = "";
    var errorVisible = false;
    
    //we know how to validate text fields based on information passed through props
    if (!valid) {
      //This happens when the user leaves the field, but it is not valid
      //(we do final validation in the parent component, then pass the result
      //here for display)
      message = this.props.errorMessage;
      valid = false;
      errorVisible = true;
    }
    else if (this.props.required && jQuery.isEmptyObject(value)) {
      //this happens when we have a required field with no text entered
      //in this case, we want the "emptyMessage" error message
      message = this.props.emptyMessage;
      valid = false;
      errorVisible = true;
    }
    else if (value.length < this.props.minCharacters) {
      //This happens when the text entered is not the required length,
      //in which case we show the regular error message
      message = this.props.errorMessage;
      valid = false;
      errorVisible = true;
    }
    
    //setting the state will update the display,
    //causing the error message to display if there is one.
    this.setState({
      value: value,
      isEmpty: jQuery.isEmptyObject(value),
      valid: valid,
      errorMessage: message,
      errorVisible: errorVisible
    });

  },

  handleBlur: function (event) {
    //Complete final validation from parent element when complete
    var valid = this.props.validate(event.target.value);
    //pass the result to the local validation element for displaying the error
    this.validation(event.target.value, valid);
  },
  render: function() {
    if (this.props.textArea) {
      return (
        <div className={this.props.uniqueName}>
          <textarea
            placeholder={this.props.text}
            className={'input input-' + this.props.uniqueName}
            onChange={this.handleChange}
            onBlur={this.handleBlur}
            value={this.props.value} />
      
          <InputError 
            visible={this.state.errorVisible} 
            errorMessage={this.state.errorMessage} />
        </div>
      );
    } else {
      return (
        <div className={this.props.uniqueName}>
          <input
            placeholder={this.props.text}
            className={'input input-' + this.props.uniqueName}
            onChange={this.handleChange}
            onBlur={this.handleBlur}
            value={this.props.value} />
      
          <InputError 
            visible={this.state.errorVisible} 
            errorMessage={this.state.errorMessage} />
        </div>
      );
    }
  }
});

The TextInput component has the simplest change because all we have to do is set the value to the props value sent to the component. We were already calling this.props.onChange from the handleChange function for real-time error processing, and simply rearranged the error processing a bit in the parent component so we can save the data. We still call the parent validation method when the user leaves the field.

We do add one additional input field to handle the textarea option. When the text field is a textarea, we have to use the textarea field. Otherwise, it’s a normal text field. There are no other changes.

var Radios = React.createClass({
  getInitialState: function() {
    //displayClass is the class we use for displaying or hiding
    //the optional "any value" text field
    return {
      displayClass: 'invisible',
      valid: false,
      errorMessage: "Input is invalid",
      errorVisible: false
    };
  },
  handleClick: function(displayClass, e) {
    //if we click any option other than the "any value" option,
    //we hide the "any value" text field. Otherwise, show it
    if (displayClass == 'invisible') {
      this.setState(
        {
          displayClass: displayClass,
          errorVisible: false
        }
      );
      this.props.onChange(e);
    }
    else {
      this.setState({displayClass: displayClass});
    }
  },
  handleAnyChange: function(e) {
    //this validation is specifically for the optional "any value" text field
    //Since we have no idea what the requirements are locally, we call the parent
    //validation function, then set the error states accordingly
    if (this.props.anyValidation(e.target.value)) {
      this.setState(
        {
          valid: true,
          errorMessage: "Input is invalid",
          errorVisible: false
        }
      );
      this.props.onChange(e);
    }
    else {
      this.setState(
        {
          valid: false,
          errorMessage: this.props.anyErrorMessage,
          errorVisible: true
        }
      );
    }
  },
  render: function() {
    var rows = [];
    var label = "";
    
    //we have passed in all the options for the radios, so we traverse the array
    for (var i = 0; i < this.props.values.length; i++) {
      //We do this little replace for when we want to display the value as part of
      //additional text. Otherwise, we would just put '[VALUE]' when passing
      //the itemLabel prop from the parent component, or leave out '[VALUE]' entirely
      label = this.props.itemLabel.replace('[VALUE]', this.props.values[i]);
      
      //You'll see that even the <br /> field has a key. React will give you errors
      //if you don't do this. This is just an axample of what's possible, but
      //you would normally add extra spacing with css
      rows.push(<input
        key={this.props.name + '-' + i}
        type="radio"
        ref={this.props.name + '-' + this.props.values[i]}
        name={this.props.name}
        value={this.props.values[i]}
        selected={this.props.value==this.props.values[i]?true:false}
        onClick={this.handleClick.bind(this, 'invisible')} />,
        
        <label key={this.props.name + '-label-' + i} htmlFor={this.props.values[i]}>{label}</label>,
      
        <br key={this.props.name + '-br-' + i} />);
    }
    
    //The "any value" field complicates things a bit
    if (this.props.addAny) {
      //we passed in a separate label just for the option that
      //activates the "any value" text field
      var selected = false;
      label = this.props.anyLabel;
      if (this.props.value != undefined && this.props.values.indexOf(this.props.value) == -1) {
        selected = true;
      }
      rows.push(<input
        key={this.props.name + '-' + i}
        type="radio"
        ref={this.props.name + '-any'}
        name={this.props.name} value="any"
        selected={selected}
        onClick={this.handleClick.bind(this, 'visible')} />,
          
        <label key={this.props.name + '-label-' + i} htmlFor={this.props.values[i]}>{label}</label>);
      
      //and now we add the "any value text field, with all its special variables"
      var value = "";
      if (selected) {
        value = this.props.value;
      }
      
      rows.push(<div key={this.props.name + '-div-' + (i+2)} className={this.state.displayClass}>
        <input
          className="anyValue"
          key={this.props.name + '-' + (i+1)}
          type="text"
          value={value}
          placeholder={this.props.anyPlaceholder}
          onChange={this.handleAnyChange}
          ref={this.props.name} />
      </div>);
    }
    
    //Now we just return all those rows, along with the error component
    return (
      <div className="radios">
        {rows}
        
        <InputError 
          visible={this.state.errorVisible} 
          errorMessage={this.state.errorMessage} />
      </div>
    );
  }
});

The only changes made to the Radios component have to do with the addition of the value attribute. You may have noticed that the default and reset values sent to the Radios and Department components are “undefined.” That’s because there’s always a possibility that one of the radio or select options could be 0 or an empty string, but both components also contain an “any value” text field. The only way to truly unset these radio and select fields, therefore, is to set the value to undefined.

Properly setting the regular radio buttons is easy. We just select the radio button using the selected attribute if it matches the value, as we iterate through each radio button:

selected={this.props.value==this.props.values[i]?true:false}

Just because we are using the value property to empty the fields doesn’t mean that we don’t have to set the current value. Remember that we are saving the state as the user makes changes, but that state change causes the display to update, which means that we have to set the value correctly even when the field is not empty. Otherwise, the fields would be set to empty as soon as a user makes a change!

We then put the “undefined” setting to use when deciding whether to select the “other” option:

var selected = false;
if (this.props.value != undefined && this.props.values.indexOf(this.props.value) == -1) {
  selected = true;
}

If the value is undefined, then we know not to select anything, because we are emptying all the fields. If it’s not undefined, however, and the value does not match any of the other radio buttons, then we know we have a custom value.

For the optional text field, we just need to set the value if it exists:

var value = "";
if (selected) {
  value = this.props.value;
}

There are no changes to the Payment component, but we do have a small change to the Department component (even though we aren’t actually saving the value):

var Department = React.createClass({
  getInitialState: function() {
    return {
      displayClass: 'invisible'
    };
  },
  handleClick: function(e) {
    //We're doing another one of these "any value" fields, only shown when
    //a specific "other" option is chosen
    this.props.onChange(e);
    var displayClass = 'invisible';
    if (e.target.value == 'other') {
      displayClass = 'visible';
    }
    this.setState({displayClass: displayClass});
  },
  render: function() {
    //This is a select field with options and sub-options, plus an "any value" field
    var value = this.props.value;
    if (this.props.value != undefined && ['none', 'muir', 'revelle', 'sixth', 'jacobs', 'global', 'medicine', 'scholarships'].indexOf(this.props.value) == -1) {
      value = 'other';
    }
    else if (this.props.value == undefined) {
      value = 'none';
    }
    
    return (
      <div className="department">
        <select value={value} onChange={this.handleClick} multiple={false} ref="department">
          <option value="none"></option>
          <optgroup label="College">
            <option value="muir">Muir</option>
            <option value="revelle">Revelle</option>
            <option value="sixth">Sixth</option>
          </optgroup>
          <optgroup label="School">
            <option value="jacobs">Jacobs School of Engineering</option>
            <option value="global">School of Global Policy and Strategy</option>
            <option value="medicine">School of Medicine</option>
          </optgroup>
          <option value="scholarships">Scholarships</option>
          <option value="other">Other</option>
        </select>
        <div className={this.state.displayClass}>
          <input className="anyValue" value={this.props.value=='other'?this.props.value:''} type="text" onChange={this.props.onChange} placeholder="Department" ref="any-department" />
        </div>
      
        <InputError 
          visible={this.state.errorVisible} 
          errorMessage={this.state.errorMessage} />
      </div>
    );
  }
});

Since this is a select field with an “any value” text field, we have to check for “undefined” again:

    var value = this.props.value;
    if (this.props.value != undefined && ['none', 'muir', 'revelle', 'sixth', 'jacobs', 'global', 'medicine', 'scholarships'].indexOf(this.props.value) == -1) {
      value = 'other';
    }
    else if (this.props.value == undefined) {
      value = 'none';
    }

The Department component is a little bit different from the others, in that the options are simply hard-coded. The only reason it’s a separate component is to simplify the code in the DonationForm component. As such, the easiest way to set the correct value is to simply check against the hard-coded values. This is similar to what we did in the Radios component, but with hard-coded values. We then set the text field based on whether they’ve selected “other.”

Saving data to the server

Now we get to save the data and watch the changes happen! Our example hinges on the installation of Node.js. Most of what needs to be done is covered in the beginner’s Node.js tutorial. If you follow all the directions in that tutorial, within the folder for your project, you’ll wind up with a package.json file. The only addition to that tutorial is to install body-parser along with express. After installing express, you will need to run the same command, but with body-parser:

npm install body-parser --save

This will give you a package.json file similar to the one included with the files for this tutorial:

{
  "name": "donation-tutorial",
  "version": "0.0.1",
  "description": "Donation tutorial",
  "main": "server.js",
  "scripts": {
    "start": "node server.js"
  },
  "keywords": [
    "react",
    "tutorial",
    "donation",
    "example"
  ],
  "author": "zenva",
  "license": "ISC",
  "dependencies": {
    "body-parser": "^1.14.1",
    "express": "^4.13.3"
  }
}

We use server.js for our example, since we are creating a server, although the file in the Node.js tutorial is called script.js. You can use either name as long as the name in your package file matches the name of your Node file.

From there, you would create your Node server in whatever way you see fit. The server can do additional processing and error checking, and should include security measures as well. It can also save information to a database, and read from a database. In our example file, we simply save to, and read from, a file called donations.json. In fact, our server is so simple that it’s very similar to Facebook’s server.js file, included within their tutorial files. You can’t really make it more simple than that!

If using the files with this tutorial, all you have to do is install Node.js (which includes npm), then go to the same folder as the package.json file and run the following command on the command line:

npm install

Once it’s installed, just run the following command:

node server.js

But look at the following line in package.json:

"start": "node server.js"

This means that you can also start the server by running the following command:

npm start

The server will then start, and tell you right where you need to go in your browser: http://localhost:3000/

Once you open that URL, you should see a list of donations, with the ability to add new donations. In addition, if you add a field directly to the donations.json file, it will display on the screen almost immediately!

Screen Shot 2015-11-17 at 8.03.00 PM

Ending Tips

There is a lot more to explore in regard to web development – and trust us, React isn’t the only way to deal with forms. So be sure to check out all your options for web development with full-stack courses. You can also just return to basics and explore web fundamentals – especially educators who have options like Zenva Schools.

BUILD GAMES

FINAL DAYS: Unlock 250+ coding courses, guided learning paths, help from expert mentors, and more.

]]>
Create a React App: Beginner’s Tutorial https://gamedevacademy.org/create-react-app-tutorial/ Mon, 16 Aug 2021 04:19:18 +0000 https://coding.degree/?p=1346 Read more]]> In this post, we’re going to explore the popular JavaScript library of React and learn the fundamentals of creating our own web app by using Create-React-App.

Why React? Well, considering it is used by over 9 million websites and is ranked as the 2nd most popular framework, you can bet these skills will pay off greatly in your success as a web developer.

Let’s get started in exploring React!

About React

React is a powerful open-source JavaScript library created by Facebook for a very specific purpose – building user interfaces. React enables developers to create complex and interactive UIs by composing together React components built with JavaScript that encapsulate UI, state, and logic.

Banner with React Logo and Purpose Statement

There are several important points to note with React:

  • When you write code in React you can render it in different environments including the web (using React-DOM), server (using Node), and on mobile (using React Native)
  • React focuses on the UI and makes no assumptions about the rest of your website or app’s technology stack
  • React forms the basis for static, dynamic, and hybrid server-side frameworks for building web apps and websites such as Next.js and Gatsby

While React’s approach creates a lot of options for developers, it can be a little overwhelming to those new to React. Options mean choices. Choices with the development environment tooling, testing, and optimization for production as well as the other technology layers involved in any full-stack app.

This is where Create-React-App (CRA) shines! CRA (https://create-react-app.dev/) is a free, open-source, command-line interface (CLI) tool created and officially supported by the React team at Facebook. CRA has been used to create millions of React apps and there’s a very good reason for that.

If you’re an experienced developer and you know you want server-side rendering (SSR), static-site generation (SSG), or any Hybrid combination then you may want to consider starting with Next.js or Gatsby. Otherwise, go ahead and use Create-React-App. In the following sections, we’ll show you how!!!

Create-React-App: An Overview

Whether creating a demo or building a new website or app, Create-React-App (CRA) gets you set up with a new React app, preconfigured for development with build tools chosen, maintained and hidden from the developer. The other great thing is the demo app created by CRA is pre-wired to run in the browser in development mode using a pre-configured development server. You can easily modify this demo to start your project.

Banner for Create-React-App Website Home Page

CRA also comes with other built-in commands to test your app, build an optimized version for production deployment, as well as an “eject” option that exposes all the hidden configuration files for the developer to take full control at any time.

The CRA environment is perfect for beginners learning to create their first React Web App, experienced developers looking to quickly start work on an idea for a Web App that will be deployed to the world and all scenarios in between. That’s why millions of apps have been created with CRA including almost every demo, tutorial, or course you’re likely to watch!

Banner image for idea

How to use Create-React-App

Normally, this is where we would talk about installation instructions except with Create-React-App (CRA) there are none! Really… you don’t need to install, configure or maintain any of the build tools normally required to create a modern web app because CRA sets up your environment using a package runner (no installs required), preconfigures your development environment and hides all this complexity so you can focus on the code.

Let’s get started by creating a project with some initial project structure, complete with a properly-wired demo React App that you can easily modify to quickly start prototyping an idea, following a tutorial, or creating the next big thing!!!

Display Image of Collage of Social Apps

Before You Begin

The only two things you need on your local development machine are Node.js (version 10 or higher) and the Node Package Manager (NPM version 5.2 or higher). Chances are you have both tools already. To verify simply open your computer’s command prompt or terminal window and enter the commands:  node --version and  npm --version

node --version
v14.15.0
npm --version
7.17.0

If you get an error indicating command not found visit nodejs.org and follow the installation instructions for your operating system (Windows, Mac, or Linux). These easy-to-follow instructions (choose LTS version) will install both node and npm.

As a note, do make sure to enable JavaScript on your browser as well – as a JavaScript-based library, even new React projects need this to function correctly.

Now you’re ready to begin!

Create App

Open your computer’s command prompt or terminal window (from now on simply referred to as terminal) to the directory location where you want to create your new project. When you run the CRA command, it will create a new folder, based on the name you provide, inside the current directory and install your entire development environment as well as React demo project in it.

Terminal Command:

npx create-react-app my-app

This command has three parts:

npx

  • NPM Package Runner CLI Tool
  • Available since NPM version 5.2
  • Execute packages from the online NPM Registry without needing to install the code package first

create-react-app

  • NPM Package to execute
  • This is the Create-React-App Command Line Interface (CLI) tool used to create your local React development environment and demo app

my-app

  • Name of the folder that will be created to store the local React development environment and your project code
  • This could be any folder name as long as it meets npm naming restrictions including no capital letters and URL-friendly characters (example: no spaces)

Running the npx CLI command above temporarily installs the latest version of create-react-app, and then executes it to create the dev environment and demo app. The following output displays in the terminal after successful completion.

Terminal Output:

Screen Shot of Create React App Creation Output

This output lets you know that CRA has completed the environment setup. It also provides the list of CRA available commands with brief descriptions (more detail in an upcoming section) and suggests your next two actions:

  1. Change directory to your new project folder (cd my-app)
  2. Start the development server which launches the demo app and makes it available in the browser (at localhost:3000 by default)

Let’s start now by running these commands in the terminal and checking out our newly created project.

Launch App

Change to the new project folder (my-app):

cd my-app

Launch the app:

npm start

This command launches the app by starting the CRA development server. The following output displays in the terminal:

Screen Shot of Create React App Development Server Terminal Output

The demo React app will automatically open in your default browser window at localhost:3000

Screen Shot of Create React App Demo App in Computer Browser

You could also open up another browser to localhost:3000 and the app will appear there as well. It’s also interesting to note the “On Your Network:” address in the above terminal message. Not surprisingly you could enter this address into a web browser and it will also show the app. What’s more interesting is that if you have a phone or other device on the same wifi network as your computer, you could open your device’s browser and enter this address and the React app will open on your device.

Screen Shot of Create React App Demo App in Device's Web Browser

Essential Files and Folders

Open your newly created React app in your favorite code editor and let’s explore the files and folders that were created by default.

Create-React-App Defaults

Running  npx create-react-app my-app creates a project folder named my-app inside the current directory. Inside my-app, Create-React-App (CRA) generates a React web app development environment along with a demo project resulting in the following project (files and folders) structure:

Screen Shot of Create React App Default Files and Folders

The project structure generated by CRA is relatively simple by default and contains everything you need to develop, test, and optimize your app for production deployment.

If you’re new to React or simply creating a demo or following a course it’s worth understanding what the generated files are, how they’re connected and what files can be deleted, added, or renamed. Chances are if you’re watching a tutorial the first thing you’ll notice the instructor do after running CRA to generate the project is start deleting a bunch of files! The following sections contain the essentials you need to know.

Development Essentials

In the image above, showing the default project structure generated by CRA, you’ll notice three folders and three files have been highlighted. The key thing they all have in common is that they must exist and have these exact names.

  • node_modules (folder)
  • public (folder)
  • index.html (file)
  • src (folder)
  • index.js (file)
  • package.json (file)

The node_modules folder contains all packages (code) downloaded from the online NPM Registry. These are the development and production dependencies of your React app. This folder is automatically updated when npm install/uninstall commands are run so it’s best if you just ignore this folder and let it remain closed. If the folder or its contents are accidentally deleted it can be recreated by running the following command (as long as the package.json file exists):

npm install .

The public folder contains the web page (index.html) which is the “single-page” in the Single Page App (SPA) generated by CRA. The other files are image and config files that are only required when building an app for production. In that case, the image and icon files would be replaced with your own and the config files would be modified accordingly. If just learning React, it’s best to ignore this folder and let it remain closed.

The index.html file is the web page which is the “single-page” in the Single Page App (SPA) generated by CRA. For a SPA, this is the only file directly fetched from the server when a user visits your web page. When the browser parses (reads) this HTML file it fetches any files referenced inside. The key reference we’re interested in is our React app which is a JavaScript file. When this file is loaded and executed by the browser, the React app comes to life and you now have a dynamic web app. For those learning React, these are the only important lines of code in the index.html file:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>React App</title>
  </head>
  <body>
    <div id="root"></div>
  </body>
</html>

The src folder contains ALL the JavaScript code and CSS styles processed by Create-React-App. If it’s not in this folder, it doesn’t exist!!! Inside the src folder, you can create as many subfolders as your want including subfolders of subfolders. You can also name these subfolders anything you like. Perhaps the most common folder name you’ll find is “components”. Many React developers will create a components folder inside the src folder to hold all React Components developed for use in the app.

As for CSS, you’ll often find two variations: separate .css files that are then imported into JavaScript components (the default option seen in the CRA demo – example below) and CSS styles embedded directly in JavaScript files (styled-components is a popular option for this approach). Note that all images, fonts, and files are added the same way as shown below with the import of both the CSS and the logo image into the App Component.

import logo from './logo.svg';
import './App.css';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

The index.js file is the JavaScript entry point CRA uses to start the build and render of your React app. In this file, React takes the code we’ve written as Components and renders them on the web page. There are several key things to note in the index.js code below:

  •  import React from 'react'; Including the main React library
  •  import ReactDOM from 'react-dom'; React can render on more than just the web so its render logic is in a separate code file. In this case, we are including the React code necessary to render on a web page (HTML) in what is known as the Document Object Model (DOM)
  • import App from './App';Including the App component which makes it available to use inside the index.js file. React builds User Interfaces (UI) by bringing together Components. In the code above, we show the App Component that contains the code to create what you see in the browser when we launched the app with the  npm start command in a previous section
  • The  ReactDOM.render() method places the App component UI inside the  <div id="root"></div> element inside the index.html file as shown above in the index.html file description
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';

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

The package.json file is the only configuration that CRA exposes to the developer. Normally this file would contain a large list of development and production code dependencies as well as build tools. There are only two key things of note for us in this file:

  • The required entries in “dependencies” section are “react”, “react-dom”, and “react-scripts”. The references to “react” and “react-dom” are the code dependencies we noted above as being imported into the index.js file so React can do its work and render that work to the web page. The reference to “react-scripts” is actually the CRA magic!!! In this single reference is the entire React web app development environment including commands to be run that we’ve been referencing throughout this article
  • The “scripts” section is the commands that CRA provides. We’ll discuss these in more detail in the next section. For now, note that each command runs the “react-scripts” and this is how CRA allows us to execute the commands to “start” the development server as well as create an optimized “build” to deploy to production

Banner for Create React App CLI Commands

Create-React-App Built-in Commands

There are two main JavaScript Package Managers (NPM and Yarn) that interact with the online NPM Registry and also run commands (“scripts”) locally in the terminal. As the following examples indicate, you can use npm or yarn (if installed).

Create-React-App (CRA) offers four built-in CLI commands, by default, when it sets up your local React development environment. These commands are exposed as a set of “scripts” defined in the package.json file and executed in the terminal. These four commands or “scripts” are:

Start

npm start or  yarn start

Starts the development server which launches your React app in development mode. You can view the app by opening localhost:3000 in the browser. The dev server will automatically reload the page any time you make changes to the React code. You’ll also be able to view build errors and warnings in the console.

Test

npm test or  yarn test

Starts the test runner in an interactive “watcher” mode. By default, runs tests against all files that have been changed since the project was last committed to a git repository.

Build

npm run build or  yarn build

When you are ready to deploy your app to production, running this build command will bundle React in production mode, minifying and optimizing all code and assets for best performance. The build produced is stored in a folder created named build. This folder contains everything needed to deploy your app to production.

Eject

npm run eject or  yarn eject

It’s important to note that this command is a one-way operation. Once you “eject” you are completely removed from the CRA environment and you can not go back! For experienced developers, this provides a great option because it enables a developer to get a quick start on creating their React app without being concerned about being locked into a controlled environment once their project had outgrown it or they wanted more configuration control.

Banner for Start React App Development

Start React App Development

The best way to learn to code… is to write code! Follow a tutorial, code along, change the code, break the code, fix the code and code something new! Focus on learning more from lessons not on completing more lessons. “I see how that works… now what if I tried this?”

To begin, let’s understand how the demo app works. Then let’s understand the basics of building and composing React components by separating the UI into several simple components which we’ll compose back together.

Installing React Developer Tools

Before we start developing it’s a great idea to install the free and officially created and supported browser extension called “React Developer Tools” which is available for most modern browsers (Chrome, Firefox, Brave, Edge).

For example, search the “chrome web store” for “React Developer Tools” and press the “Add” button. This adds two React-specific tabs (Components and Profiler) to the existing browser dev tools.

Screen Shot of React Developer Tools Install Page

The components tab is a great asset for both developing a React app as well as learning React as it helps you visualize and interact with React components and subcomponents including any information they’re holding in React State, Props, Hooks and more.

Open your browser dev tools with your menu (dev-tools), keyboard shortcut (Option + ⌘ + J on Mac | Shift + CTRL + J on Windows) or right-click your web page and select “inspect”. With dev tools open select the “Components” tab when on a page running React.

How Components are Composed and Rendered

Start by opening a terminal window in your project’s main folder then execute the “start” command to open the React development server:

npm start

The following output displays in the terminal:

Screen Shot of Web page with React Dev Tools open

Your React app will automatically open in your default browser window at localhost:3000

React app open with localhost:3000

Open the browser dev tools and select the Components tab. Notice that we have only one component (App).

This page is rendered by linking three key files:

  • public/index.html
  • src/index.js
  • src/App.js

public/index.html

The important line of code to notice is  <div id="root"></div> which is where our React app will be placed.

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>React App</title>
  </head>
  <body>
    <div id="root"></div>
  </body>
</html>

src/index.js

The three important lines of code to notice are:

  • import App from './App'; which is how we include the file named App.js containing our App Component
  • <App /> which is how we place the App Component
  • document.getElementById('root') which is how we link to the HTML element where we want to place the React app
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';

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

src/App.js

This file contains the App Component with the JSX (HTML- looking syntax in the JavaScript code) to be displayed on the Web page where this component is placed.

import logo from './logo.svg';
import './App.css';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

Building an App with Components

Next, Let’s divide the App.js code into several Components. Normally each component would be placed in its own file within a components folder adhering to naming conventions. For example, the file’s name and component’s name should be the same and both should start with a capital letter. For simplicity of illustrating the point in this lesson, we’ll keep all components within the App.js file.

import logo from './logo.svg';
import './App.css';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <Logo logo={logo}/>
        <Message/>
        <Message text="Bootstrapped with Create React App"/>
        <ReactLink linkText="Learn React"/>
      </header>
    </div>
  );
}

export default App;

/* Logo component 
- normally in separate file: src/components/Logo.js*/
function Logo(props) {
  return (
    <img src={props.logo} className="App-logo" alt="logo"  />
    );
  }

/* Message component 
- normally in separate file: src/components/Message.js*/
function Message({text}) {
  return (
    <p>
    { text || 'My React App'}
  </p>
  );
}

/* ReactLink component 
- normally in separate file: src/components/ReactLink.js*/
function ReactLink({linkText}) {
  return (
    <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
         {linkText}
        </a>
  );
}

When the React development server is running, any change you make to your code is automatically reflected on the web page. You can see in the Components tab that originally we had only one component (App) and now we still have App but nested inside App is four other components including the Message component that we used twice.

Screen Shot of App and Dev Tools - before and after

Important React notes about code above:

  • props are used to pass static data (text) or dynamic data (variables)
  • props are passed using a syntax similar to HTML attributes except that variables are enclosed in curly braces ( {…} ) whereas static data (text) is enclosed in quotes ( “…” )
  • props are received by a component within the function parameters as an object variable named “props”. The properties and values of this object are the names and values you used on the component in the parent. For example, “logo” for the Logo component and “text” for the Message component. The value can be referenced within the component by using  {props.[name]} such as {props.logo} or destructured as it is passed into  function Message({text}) {...} . When destructured, the property can be used directly  <p>{ text || 'My React App'}</p> and in fact, we can use any JavaScript expression inside the curly braces. In this case, we have default text which will appear if no text is passed in as a prop

This ability to compose small, self-contained, reusable components is one of the things that make working in React a great developer experience.

Banner for Software Testing

Test App

Testing is critical for any application intended for actual use!!!

With the importance of testing in mind, Create-React-App (CRA) includes running tests as one of its core features. The default React development environment generated by CRA has several important “test” elements:

  • Built-in test runner (Jest)
  • CLI command (“script”) to start the test runner
  • Working test file coded to test the demo app

To start the test runner inside CRA, execute the following command:

npm test

This command starts the test runner in an interactive “watcher” mode. By default, tests are run against all files that have been changed since the project was last committed to a git repository. The interactive test runner then asks you what files you want it to watch for changes the next time you run a test. The following is what appears in the terminal window after executing the “test” command above.

Screen Shot of the terminal output after starting CRA interactive test runner

Testing is a huge topic in itself and guidance on how to write tests is outside the scope of this tutorial. If you are new to programming or new to React and your focus is on following tutorials to learn the fundamentals of React then you’ll likely avoid writing formal tests. At this level, writing code along with a tutorial likely won’t focus too heavily (if at all) on working with a test runner and that’s okay.

The reason it’s okay is that coding along with a React fundamentals course likely won’t meet the standard of necessity stated at the beginning of this section “intended for actual use”. When you’re ready to learn more about testing in React you can start with the official React testing docs, Create-React-App testing docs, and the Jest test runner website.

As a final note, if you are new to programming, you may hear developers talk about unit testing and debugging. Each time you update your code and the browser refreshes the act of noticing if the page is working as expected and observing if there are errors in the console means you are “unit testing” your app. When you take action to determine the cause of the errors and fix them you’re entering the territory of “debugging”. This can involve logging information to the console, ensuring the information inside the React Developer tools, that we installed in a previous section, is as expected and taking action in your code to fix the issue, using the browser’s developer tools for debugging, using your code editor’s debugging tools or working with external developer tools.

As we noted above, both “testing” (identifying errors) and “debugging” (finding the root cause of the error and fixing it) are huge topics in themselves. As you work professionally, perhaps as part of a team, you’ll become aware of various levels of testing ranging from the “unit testing” we’ve discussed so far (which is generally performed by a developer) to “integration testing”, “system testing”, “end-to-end” testing and more (which are generally performed by business or functional roles). Generally, the higher you go, the more critical the application being tested, and the context of the application within a larger ecosystem of related apps the more higher-level testing will be required and the more likely test runners, code coverage, and continuous integration testing will become your reality.

For now, when you’re ready to learn more about debugging options you can start with the Create-React-App debugging docs and take it from there!

Banner for Build and Deploy of App

Build and Deploy React App

Software applications are never done!!! When you complete an iteration of your application that you’re ready to move to a production environment that makes it available to a wider group of users or to a public Internet address for the world to discover there is one important step to complete first – optimizing your app and its static assets.

Build – Optimize React App

npm run build

When you are ready to deploy your app to production, running this build command will bundle React in production mode, minifying and optimizing all code and assets for best performance. The build produced is stored in a folder created named “build“. This folder contains everything needed to deploy your app to production.

The best way to test your optimized app before actually deploying it to production is to install an HTTP server locally that will serve your main web page ( index.html file from the newly created build folder). This way, you ensure that your app and all its links and static assets work in production mode. To do this install an NPM package called “serve” as follows:

npm install serve

This “serve” package (which is an HTTP server) is installed locally on your computer and added to the node_modules folder with a config reference placed in the package.json file. If this is something you’ll be using often across multiple projects then it can be installed globally by adding the (-g) flag:  npm install -g serve

To serve our optimized app (from the build folder) run the following command:

serve -s build

This command serves our static site on localhost:5000. Open a browser to this address and you’ll see your production React app just as someone visiting your site from the Internet would see it.

Deploy – Hello World!!!

While you wrote all your code in the src folder and perhaps made adjustments to the index.html file, images, icons, or other static assets in the public folder; everything you need to deploy to production is placed in the build folder after the  npm run build is executed.

There are many options (locations) to deploy your React application for the world to see. The best place to start is the Create-React-App deployment docs which contain options, instructions, and links to guide you through the deployment process.

Banner for Beyond the Basics Section

Beyond the Basics

Selecting a Package Manager

There are two main JavaScript Package Managers (NPM and Yarn) that interact with the online NPM Registry and also run commands (“scripts”) locally in the terminal.

If you do not have Yarn installed on your computer, CRA will use NPM to set up the React development environment as well as install any development and production dependencies.

If, however, Yarn is installed when CRA creates a new app, the CLI will use Yarn instead of NPM. If you prefer to use NPM, you can append  --use-npm when running the CRA creation command.

npx create-react-app my-app --use-npm

Uninstalling Old CRA Versions

Before the NPM Package Runner concept (npx) was introduced in npm version 5.2, create-react-app was generally installed globally via  npm install -g create-react-app. While this method of installation is not recommended, it is still an option.

If you have previously installed create-react-app using this method, it is recommended that you uninstall this package to ensure npx always uses the latest version.

You can easily uninstall create-react-app global installations (-g) using one of the following commands (either from npm or yarn).

npm uninstall -g create-react-app

or

yarn global remove create-react-app

Create-React-App using Templates

Create-React-App (CRA) templates serve two purposes:

  1. Local React development environment including build tools and commands as well as NPM code packages required for both development and production
  2. Files and Folders that your React project will contain when initially created

When you run the basic npx command to create your React development environment it uses the Create-React-App official base template named cra-template.

You can now optionally start a new app by appending officially supported templates such as TypeScript (–template typescript), Redux (–template redux), or Redux-Typescript (–template redux-typescript):

npx create-react-app my-app --template redux-typescript

You can also append community-created templates in the same manner. Search NPM ( https://www.npmjs.com/search?q=cra-template-* ) to see the many available options.

npx create-react-app my-app --template [template-name]

You can also build your own template following these official instructions: https://create-react-app.dev/docs/custom-templates/

Banner in Beyond the Basics section

Adding TypeScript to React App

TypeScript is an open-source language that builds on JavaScript by adding optional static type definitions. This brings to JavaScript the tooling and development power of strongly typed languages (such as Java and C#) without losing the reach and flexibility of JavaScript itself. Since any valid JavaScript is automatically valid TypeScript, it can be gradually adopted.

While JavaScript frameworks such as Google’s Angular use TypeScript by default its use in React is optional (but growing). You can start a new React app using TypeScript by appending the officially supported TypeScript template (–template typescript) to the Create-React-App npx command.

npx create-react-app my-app --template typescript

If you want to add TypeScript to an existing React app, just follow these official instructions: https://create-react-app.dev/docs/adding-typescript/

Analyze React App

By default, CRA includes the ability to measure and analyze the performance of your React app using different metrics. In the src folder is a file named reportWebVitals.js. This file contains a function named  reportWebVitals() that accepts a function (such as  console.log ). When this function is included in the index.js file, it is fired when the values of any of the metrics you’re tracking calculate on the page. The captured values can simply to logged locally or sent to an online endpoint.

Measuring app performance is a significant topic in itself. To get started, you can check out the CRA official documentation on web vitals and capturing analytics.

Banner for Conclusion section

Conclusion

React is an awesome JavaScript library loved by developers all over the world. While React’s approach creates lots of options for developers, it can be a little overwhelming to those new to React. Where there are options, there are decisions to make. These decisions include your local development environment and extend into all areas of software development, testing, and optimization.

To avoid the daunting task of setting up and maintaining your build tooling as well as wiring up your initial app, Facebook (creator and maintainer of React) has released an official command-line interface (CLI) tool called Create-React-App (https://create-react-app.dev/) to take care of all this complexity for you.

If you’re an experienced developer and you know you want server-side rendering (SSR), static-site generation (SSG), or any Hybrid combination then you may want to consider starting with Next.js or Gatsby. Otherwise, Create-React-App is what you want to quickly kickstart your next React project, prototype an idea, follow a tutorial or create the next big thing!!!

Good luck and happy coding!!!

BUILD GAMES

FINAL DAYS: Unlock 250+ coding courses, guided learning paths, help from expert mentors, and more.

]]>
Beginner’s Guide to React Props & States https://gamedevacademy.org/react-props-states-tutorial/ Mon, 02 Nov 2020 01:00:56 +0000 https://coding.degree/?p=448 Read more]]>

You can access the full course here: Craft Web Forms with React

React Project Setup

In this lesson, we’ll be learning how to set up our environment for building our application.

Summary

We’re going to be using a tool made by Facebook called React, that provides a starter project and built-in build tools so we can skip to the fun part– creating our app.

The tools we’ll need are:

Installing Node.Js

First, we’re going to install Node.js. This is an open-source server environment that allows you to run JavaScript on the server.

You can download it from here: https://nodejs.org/en/download/

(At the creation of this video, the latest is 14.3.0.)

Once the download is complete, unzip node package and run the install.

Node.js setup wizard

Installing NPM

NPM is a package manager for Node.js packages. The NPM website https://www.npmjs.com/ hosts thousands of free packages to download and use.

NPM website screenshot

The NPM program is installed on your computer when you install node.js.

Installing Google Chrome

If you don’t have Chrome already installed on your system, you can download it from here: https://www.google.com/intl/en/chrome/

Google Chrome download screen

We recommend using Google Chrome over other web browsers, as the React Developer Tools is a Chrome dev tool extension for the open-source React JavaScript library.

It allows you to inspect the React components hierarchy in the Chrome developer tools. (Add it to Chrome: https://chrome.google.com/webstore/)

React Developer tools extension

Installing Visual Studio

Next, you’ll need a code editor, and we’ll be using Visual Studio. Head over to http://code.visualstudio.com/ and install.

Visual Studio Code website screenshot

Installing Create React App

To install Create React App, open up the terminal and type in the command:

npm init react-app pet-form*

*[or whatever the name you want to associate with the directory]

Mac Terminal showing React installation

…and that will create a directory with all of your React components needed to get started.

Folder structure as seen on PC for React project

Data Flow – Part 1

In this lesson, we’re going to review how data flows within React by inspecting what are props and states and when to use them.

Probs vs. States

Infographic showing difference between React Props and States

Props, short for properties, are immutable, meaning they are unchanging. They’re also used to pass data down from your view-controller, and our inputs that describe what we should see.

States are objects. They’re mutable, meaning they can be changed. They can be private or public to their children components and may hold information that influences the output of a React component.

Showcase of the biggest differences between React Props and States

States and props are both plain JavaScript objects. While both hold information that influences the output of render, props get passed to the component (similar to function parameters), whereas states are managed within the component (similar to variables declared within a function).

Building a simple app

Let’s try building a simple app to see states and props in action.

Our app will allow us to create a list of dog names, which will include a title, a text field, and an add button to add typed names to a list of those cool dog names.

Mockup of simple React form project

Creating A React Project

Open up your terminal/command prompt, and type in your directory where you wish to put all your react projects.

For example, if you have a folder on the desktop called React:

cd Desktop/React

Then, use the Create React App command to generate a new project. We’re going to call the directory “states-props”.

nps create-react-app states-props

This will create a directory and install all the necessary packages.

Windows Command prompt showing React installation process

Now we’ll move into that directory by typing in:

cd states-props

And the generator project contains some files we won’t need right now, so we’ll delete them by doing:

rm src/App.* src/index.css src/logo.svg

Creating A DogApp.js

Next, let’s open up Visual Studio and create a new JavaScript file in ~/states-props/src.

New File window for Visual Studio Code

DogApp project being created for React Project

First, we’ll need to import the React by typing:

// JavaScript source code
import React from 'react';

Then we’re going to create a class called “DogApp” that extends React.component:

// JavaScript source code
import React from 'react';

class DogApp extends React.Component {

In that render function, we’re just going to return a <div> with a heading “My Dogs” and a button “Add a dog”.

// JavaScript source code
import React from 'react';

class DogApp extends React.Component {

    render() {
        return (
            <div>
                <h1>My Dogs</h1>
                <button>Add a dog</button>
            </div>
        );
    }
}

And then go ahead and export default DogApp.

// JavaScript source code
import React from 'react';

class DogApp extends React.Component {

    render() {
        return (
            <div>
                <h1>My Dogs</h1>
                <button>Add a dog</button>
            </div>
        );
    }
}

export default DogApp;

Project Preview

To see what we have so far, we’re going to open our index.js file:

Index.js file selected in React project folder

… and edit the file as below:

import React from 'react';
import ReactDOM from 'react-dom';
import DogApp from './DogApp';

ReactDOM.render(
  <React.StrictMode>
    <DogApp />
  </React.StrictMode>,
  document.getElementById('root')
);

Screenshot of code that needs to be deleted

Next, we’ll open up the terminal, and type:

npm start

Then once our project is loaded, we should be able to see a title and a button.

Demo of React form project progress

Data Flow Part 2

In this lesson, we’ll continue to build out our cool dog app.

Review

Remember, the objective of this app is to show States are:

  • Objects
  • Mutable (changing)
  • Can be private or public to its children components
  • May hold information that influences the output of a component

Creating A State

Open up “DogApp.js” and create a state above our render function, by typing:

state = {}

First, we’ll add two properties to the state object.

    state = {
        nameOfNewDog: '',
        dogs: []
    }

One is “nameOfNewDog”, which will hold the new name for your dog. Then, we’ll create the “dogs” array, which will hold a list of entered dog names.

In our render method, we’ll add an input tag with an onChange event.

  render() {
        return (
            <div>
                <h1>My Dogs</h1> 
                //The onChange event detects when the value of an input element changes. Here, we can bind a handleChange action to our input tag.
                <input onChange={this.handleClick.bind(this)} name="nameOfNewDog" />
        );
    }

Let’s also add an onClick event to our button tag and bind a “handleAddDog” click action to it.

The .bind() method allows us to pass the context we want to bind the function to (in this case, handleChange and handleAddDog), but it does not immediately run the actions. Instead, a copy of the action with the switch context is returned. This copy can then be run whenever you want. Note that both functions will be modifying the state object.

In our handleChange method, we can use this.setState method to set the nameOfNewDog to the inputted value.

    handleChange(e) {
        this.setState({
            nameOfNewDog: e.target.value
        });
    }

Then, in our handleAddDog click, we create an if statement that makes sure the input isn’t empty.

    handleAddDogClick() {
        if (!this.state.nameOfNewDog) {
            return;
        }
    }

And then, we use the this.setState to make sure that on the click of the button, nameOfNewDog string becomes empty, and we add that inputted value to our dogs array.

 handleAddDogClick() {
        if (!this.state.nameOfNewDog) {
            return;
        }

        this.setState({
            nameOfNewDog: '',
            dogs: [...this.state.dogs, this.state.nameOfNewDog]
        });
    }

About this.setState

Note that the way we use this.setState here can be used to modify any property in a react state object.

In traditional JavaScript, you would typically modify the object directly, but we do not recommend modifying the state directly because may cause it to get overwritten and create inconsistencies in the app. this.setState doesn’t modify the state directly but creates a pending state transition.

Another important thing to note is when you’re updating your react state tree, it only modifies the first level of the property.

Displaying State Data

So far, we’ve discussed what react states are, and how to add, update the data within them. Your next question might be, How do we display the data we’ve saved in the state?

    render() {
        return (
            <div>
                <h1>My Dogs</h1>
                <input onChange={this.handleChange.bind(this)} name="nameOfNewDog" />

                <ul> //The HTML <ul> element represents an unordered list of items, typically rendered as a bulleted list.
                    {this.state.dogs.map((dogs, i) => (
                        <li key={`${dogs}_${i}`}>
                            <b>{dogs}</b>
                        </li>
                    ))}
                </ul>

                <button onClick={this.handleAddDogClick.bind(this)}>
                  Add a dog
                </button>
                <button>Add a dog</button>
            </div>
        );
    }

With this code, we’ll be looping through the dogs array with the map method to create a list tag that outputs the name of the dogs we’ve entered.

Let’s save the project and open up the terminal to see what we’ve got. Remember to move into the relevant directory first:

cd Desktop/React/states-props

… and then run the app by typing:

npm start

Now we have our input along with our button, and within the input, we can start typing names and adding them to our list.

Dog App project showing list of names

Utilizing Props

Now that we have built a react application that utilizes state to save and display data, it’s time to take a look at how react props play with states.

Remember that Props are:

  • Immutable (unchanging)
  • Used to pass data down from your view controller
  • Inputs that describe what we should see

In our input tag, let’s insert an input of type to equal text. And if we add another input named placeholder, it will make our input field look different to our user.

<input type="text" placeholder="Enter a dog name" onChange={this.handleChange.bind(this)} name="nameOfNewDog" />     //In this case, inputs equal props.

In the same file, let’s create a new component called Dog, which will expect a prop called name.

class Dog extends React.Component {
    render() {
        return (
            <li>
                <b>{this.props.name}</b>
            </li>)
    }
}

Now, we’ll update the code in the DogApp component where we display a list of dog names.

render() {
        return (
            <div>
                <h1>My Dogs</h1>
                <input type="text" placeholder="Enter a dog name" onChange={this.handleChange.bind(this)} name="nameOfNewDog" />
                <ul>
                    {this.state.dogs.map((dogs, i) => (
                        <Dog key={`${dogs}_${i}`} name={dogs}/>                        
                    ))}
                </ul>
                <button onClick={this.handleAddDogClick.bind(this)}>
                    Add a dog
                </button>
            </div>
        );
    }

All we’re doing here is passing the dog name that we’ve stored in our state object, and passing it as a prop to the dog component we’ve just created.

                <ul>
                    {this.state.dogs.map((dogs, i) => (
                        <Dog key={`${dogs}_${i}`} name={dogs}/>                        
                    ))}
                </ul>

The dog component will then display the input name and display the name in a list item HTML tag.

Let’s save and refresh the page. Now, if we take a look at our developer tools (Ctrl+Shif+I) and go to the Components tab…

Components option in Visual Studio Code for React project

…we’ll see that we have a higher-level DogApp component, and within that, we have our Dog component, which has props of name (i.e. Charlie, Max, Buddy…):

Dog componente for Dog React App

Unidirectional Data Flow

When we combine props and states, we get the concept of unidirectional data flow.

In general, this concept means that data has one and only one way to transfer to other parts of the application.

In react this means that state is passed to the view and to the child components, triggering actions.

Image showing View pointing to Actions

Actions, triggered by the view, can update the state and the state change is passed to the view.

Image showing relationship between Actions, States, and View

When to use States?

That leads us to the question: when do we use states? As a general rule, data stored in states should be referenced inside render somewhere.

Component states are for storing UI states, i.e. Things that affect the visual rendering of the page. Here are some examples:

  • User-entered Input (values, boxes, form fields, etc.)
  • Current or selected item (current tab, selected row, etc.)
  • Data from the server (list of products, no. of likes, etc.)
  • Open/closed state (expanded/hidden sidebar or module, etc.)

This makes sense because anytime the state is updated, the component will re-render. If modifying a piece of data does not visually change the component, the data shouldn’t go into a state.

 

Transcript

React Project Setup

Welcome back. In this lesson, we’ll be learning how to set up our environment for building our application. Don’t worry, there’s no boilerplate to clone from GitHub, no webpack config either. Instead, we’re using Create React App, a tool Facebook made. It provides a starter project and built-in build tools so we can skip to the fun part, creating our app.

The tools we’ll need are Node.js, NPM, Google Chrome, React Developer Tools, Visual Studio Code, Create React App.

First we’re going to install Node.js. This is an open-source server environment that allows you to run JavaScript on the server. Go ahead and to go Node.js.org. At the creation of this video, the latest is 14.3.0. Click the download link to download. Once it has completely downloaded, navigate to your download folder, unzip node package, and run the install.

NPM is a package manager for Node.js packages. Ww.npmjs.com hosts thousands of free packages to download and use. The NPM program is installed on your computer when you install Node.js.

Next, we’ll need Google Chrome or any modern browser, but I recommend using Google Chrome simply because we’ll be using the React Developer Tools, which is a nifty tool for debugging your applications. If you don’t have Chrome already installed on your system, just go ahead and open up any browser and Google “Chrome download.” The first link will take you to a page where you will be able to do just that.

Once you have installed Google Chrome, you’ll need to install React Developer Tools. This is a Chrome dev tool extension for the open source React JavaScript library. It allows you to inspect the React components hierarchy in the Chrome developer tools.

Next, you’ll need a code editor. The one I’ll be using is Visual Studio Code. Head over to code.visualstudio.com and install.

Finally, we’ll install Create React App by going to the terminal and typing the command npm init react app and whatever the name you want to associate with the directory, and that will create a directory with all of your React components needed to get started.

With our environment all set, we can get to coding. See you next time.

Data Flow – Part 1

Welcome back, at this point you have Node.JS, NPM, Visual Studio Code, React Developer Tool and Create React App installed. All of the tools are ready, but before we dive into the art of creating a form using React, let’s review how data flows within React by inspecting what are props and states and when to use them.

Props short for properties, are immutable, meaning they are unchanging, they’re also used to pass data down from your view-controller, and our inputs that describe what we should see.

States are objects, they’re immutable, meaning they can be changed. They can be private or public to it’s children components. And may hold information that influenced the output of a react component.

States and props are both plain JavaScript objects. While both hold information that influences the output of render, they are different in one important way. Props get passed to the component, similar to function parameters, whereas states are managed within the component similar to variables declared within a function.

Let’s try our hand at building a simple app to see states and props in action. Our app will allow us to create a list of cool dog names, which will include a title, a text field, an add button to add typed names, to a list of those cool dog names.

Open up your terminal, and in your desired directory, I have a folder on the desktop called React, where I’ll be putting all my projects. Use the create React app command to generate a new project. And that command is NPX create React app. I’m gonna call my directory states dash prompts. It will create a directory and install all the necessary packages.

From here we’ll move into that directory by doing sd states dash props, and the generator project contains some files we won’t need right now, so we’ll delete them. Or you could also just ignore them. The command to delete these files is rm source backslash app dot star source backslash index dot CSS source backslash logo dot cvg.

Open your project on Visual Studio Code, and in the source folder, create a new JavaScript file titled Dog App. First we’ll need to import the React by typing import React from React. Then we’re gonna create a class called Dog App that extends React dot component, in that render function we’re just going to return a div with a heading my dogs and a button, add a dog, and then go ahead and export default Dog App.

To see what we have so far, we’re gonna go back to our index .JS file and delete import index .js and change import app to import Dog App. Then within our render, we’re just going to change that to Dog App, and erase that service worker cause we don’t really need those files to run our program.

Next we’ll open up the terminal, and type NPM start. Then once our project lobes, we’ll see that we have a title called My Dogs and then a button that has a added dog tag, and we are on our way to building the coolest Dog App ever.

In the next lesson, I’ll show you how to add those states and prompts, update them and go ahead and list those dog names, that the user types in. See you next time.

Data Flow – Part 2

Welcome back. In this lesson we’ll continue to build out our cool dog app. Remember, the objective of this app is to show states are objects, are mutable, can be private or public to its children components, and may hold information that influences the output of a component.

Now, let’s create a state. Above our render function, go ahead and type state, equals, open and close parentheses. That’s how easy it is, but this state object is useless until we start adding some data to it. First, we’ll add two properties to the state object. One is nameOfNewDog that will hold the new name for your dog as you are typing. And the dogs array, which is going to be an array that will hold a list of entered dog names.

In our render method, we’ll add an input tag with an onChange event. The onChange event and react detects when the value of an input element changes. Here, bind a handleChange action to our input tag.

While we’re here, let’s also add an onClick event to our button tag and bind a handleAddDog click action to it. The bind method allows us to pass the context we want to bind the function to, in this case our handleChange and handleAddDog click actions. But it does not immediately run the actions. Instead, a copy of the action with the switch context is returned, this copy can then be run whenever you want. It is important to note that both functions will be modifying the state object.

Now we just have to write them. So, in our handleChange method we use the this.setState method to set the nameOfNewDog to the inputted value. Then, in our handleAddDog click, we create an if statement that makes sure the input is not empty. And then we use the this.setState to make sure that on the click of the button, nameOfNewDog string becomes empty and we add that inputted value to our dogs array.

Notice how we’re using this.setState. This is the correct way of modify any property in a react state object. In traditional JavaScript, you would typically modify the object directly, but that’s a big no-no in practice. This is because modifying the state directly may create a situation where those modifications may get overwritten and cause inconsistencies in the app. setState does not modify directly but creates a pending state transition.

Another important thing to note is when you’re updating your react state tree, it only modifies the first level of property.

So far, we’ve discussed what react states are and how to add, update, the data within them. Your next question might be, how do we display the data we’ve saved in the state? This is done really easily. With this code I’m typing now, we’ll be looping through the dogs array with the map method to create a list tag that outputs the name of the dogs we’ve entered.

Go ahead and save your project and open up the terminal to run it and see what we’ve got. So, just type npm start and it will run our server and take us to our Google Chrome web browser. And from there we see that we have our title. Now we have our input, along with our button, and within the input we can start typing names and adding them to our list.

So far, we’ve built a react dog application that utilizes state to save and display data. Now we can take a look at how react props play nicely with states. Remember, props are immutable, meaning unchanging. They are used to pass data down from your view-controller, and are inputs that describe what we should see.

In our input tag, let’s insert an input of type to equal text. And if we add another input-named placeholder, it will make our input field look different to our user. Inputs, in this case, equal props. It works the same way with react components.

In the same file let’s create a new component called Dog. Dog will expect a prop called name. Now update the code in dog app component where we display the list of dog names. All we are doing here is passing the dog name that we’ve stored in our state object, and passing it as a prop to the dog component we’ve just created. The dog component will then display the input name and display the name in a list item HTML tag.

Then we go ahead and open up our terminal again, hit npm start, and our application builds out. We still have our My Dogs title with our input. And when we go ahead and type our names in there it adds to our list.

If we take a look at our developer tools, we’ll see that we have a higher level dog app component and within that we have our dog component, which has props of name, which is the first one, CeCe, and the second one, Coolest Dog Ever.

When we combine props and states, we get the concept of unidirectional data flow. In general, this concept means that data has one and only one way to transfer to other parts of the application. In react this means that state is passed to the view and to the child components. Actions are triggered by the view, actions can update the state, and the state change is passed to the view and to the child components. And it just goes around and round like that.

That leads us to the question: when do we use states?

As a general rule, data that is stored in states should be referenced inside render somewhere. Component states is for storing UI states. Things that affect the visual rendering of the page. This makes sense because anytime state is updated, the component will re-render. If modifying a piece of data does not visually change the component, the data shouldn’t go into a state.

Here are some things that makes sense to put in a state. User-entered input, such as values, text boxes and other form fields. Current or selected item, the current tab, the select row. Data from the server, so things such as a list of products, the number of likes on a page. And open/closed state, so a module open or closed, or a sidebar, expanded or hidden.

And there we have it, our data flow lesson is complete. In our next lesson we’ll go over input controls. See ya next time.

Interested in continuing? Check out the full Craft Web Forms with React course, which is part of our Full-Stack Web Development Mini-Degree.

]]>
Build a Static Tweet Mockup with React https://gamedevacademy.org/react-tweet-tutorial/ Fri, 03 Jul 2020 15:00:34 +0000 https://html5hive.org/?p=2601 Read more]]>

You can access the full course here: Bite-Sized React

File & Base Setup

In this lesson, we use what we’ve learned about JSX to build a composable UI using the example of a Tweet!

The Tweet structure will have an Avatar, Name, HandleName, Relative Time, Message, and 4 Icon Buttons.

Tweet structure broken down

Just as we discussed in detail in the HelloWorld section, make sure you have your Terminal open and are in the directory where you want to create your new project. In the video lesson a project directory on the Desktop called React is used to hold all course projects (you can choose any directory location and name). Use your terminal to change into your project directory.

Commands to change into React directory

Now that your terminal is in the project directory, use the Create-React-App command to begin a new project. In the terminal, enter the command:

npm init react-app static-tweet && cd static-tweet

This command will create a basic working React app called static-tweet, install our dependencies from NPM and finally change the working directory to be our new project inside the terminal.

Project creation command for static-tweet project

The generated project contains some files we won’t be using for this demo so you can ignore them or delete them with this command:

rm src/App.* src/logo.svg src/s*.js

Open your project in VS Code. Either open the application VS Code and use File/Open from the menu or type the following into the terminal:

code .

In the video lesson we start by adding FontAwesome to our React project. FontAwesome gives us access to the icons we will use in this lesson for buttons we are creating. To access these icons we will need to add it as a stylesheet in our index.html file. In VS Code, open the index.html file in the public folder to add this link statement:

<!-- index.html -->
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.12/css/all.css"/>

Place this stylesheet link in the <head> section of index.html just above the <title> tag:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <!-- (start) FontAwesome link - add this line to include Icons -->
    <link
      rel="stylesheet"
      href="https://use.fontawesome.com/releases/v5.0.12/css/all.css"
    />
    <!-- (end) FontAwesome link -->
    <title>React App</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
  </body>
</html>

You can browse or search for icons on the FontAwesome website: https://fontawesome.com/icons?d=gallery&m=free.

In VS Code, open the src/index.css file and add the styles for a tweet class by copying from the course download files or text below:

/* index.css */
.tweet {
  border: 1px solid #cccccc;
  width: 564px;
  min-height: 68px;
  padding: 10px;
  display: flex;
  font-family: "Helevetica", arial, sans-serif;
  font-size: 14px;
  line-height: 18px;
}

While CSS is outside the scope of this course, including the CSS from the download files will make your app look better by adding border, width, height, font style and padding around our tweet element.

Tweet Component

Next, we’ll setup our src/index.js file in a similar way as we did in the HelloWorld lesson. Start by deleting all the contents and then import React and ReactDom modules as well as the index.css we created above.

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

React will need to be imported into all files that use React.

ReactDom is needed only needed in this index.js file to render the React code to the web page HTML known as Document Object Model (DOM).

Note: Notice that the CSS is imported in a different way. The first thing to realize is that we are importing the entire index.css file and secondly notice that it is not simply imported using a string (which is interpreted as a node dependency like ‘react’). We actually import a relative path ‘./’ (meaning in the same directory as current file) and use the file extension ‘.css’ otherwise ‘.js’ would be assumed.

Tweet Component

Next create the Tweet Component just like we created the HelloWorld component in a previous lesson.

// index.js
function Tweet() {
  return (
    <div className="tweet">
      Tweet
    </div>
  );
}

Note: In the JSX lessons, we noted that while JSX is a HTML-like syntax there are a couple things to watch out for. One is that while we would reference a class in HTML with the class keyword, we cannot do that in JavaScript (JS) since class is a JS keyword. React instead uses className.

Finally, we add our render logic and our index.js file now looks like this:

// index.js
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";

function Tweet() {
  return <div className="tweet">Tweet</div>;
}

ReactDOM.render(<Tweet />, document.querySelector('#root'));

Test the App

In the terminal, start the app by typing:

npm start

You see your Chrome browser open up to localhost:3000 and display something like this:

Tweet test from React project

Open Google Developer Tools by inspecting the page. Under the Elements tab notice in the <head> of the document there is a <style> tag that we didn’t put there. This is the contents of our index.css we imported into our index.js JavaScript file.

Tweet Sub-Components

Next, it’s time to build some components that will be composed together inside the Tweet Component.

Let’s start with Avatar which will be a component that returns an <img> tag. Code the following function inside index.js:

// index.js
function Avatar() {
  return (
    <img
      src='https://gravatar.com/avatar/nothing'
      alt='avatar'
      className='avatar'
    />
  );
}

Next, add some CSS to our index.css file for the class of avatar:

.avatar {
  width: 48px;
  height: 48px;
  border-radius: 5px;
  margin-right: 10px;
}

Lastly, we can now modify our Tweet Component to use the Avatar Component alongside the word Tweet:

// index.js
function Tweet() {
  return (
    <div className='tweet'>
      <Avatar />
      Tweet
    </div>
  );
}

Finally, with the render logic included, our index.js file now looks like this:

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

function Tweet() {
  return (
    <div className='tweet'>
      <Avatar />
      Tweet
    </div>
  );
}

function Avatar() {
  return (
    <img
      src='https://gravatar.com/avatar/nothing'
      alt='avatar'
      className='avatar'
    />
  );
}

ReactDOM.render(<Tweet />, document.querySelector('#root'));

Our browser output now looks like this:

Tweet test with React Dev Tools showing Components

Open the Chrome Developer Tools and select the Components tab. As discussed in the Getting Started section, the Components Tab is installed with the React-Developer-Tools and allow us to view React in terms of components. In other words, we see the app the way React sees it.

Notice our Tweet is now composed of two components; the parent Tweet and child Avatar.

Final Details

In the last lesson we started to build our static tweet. We got as far as putting our Avatar within our Tweet. Next, we’ll add the Message, Time, Name and Handle components.

Tweet structure for React static tweet project

Keep in mind our desired Tweet Structure, let’s first code our static Message Component, we’ll simply return a string of text ensuring we wrap the text in a <div> (because we want it on its own line) and provide a className so we can add CSS style. Ensure to copy the CSS from the course download files in the static-tweet directory in the src/index.css file.

// index.js
function Message() {
  return (
    <div className="message">This message is less than 140 characters!</div>
  );
}

Next, let’s code our NameWithHandle Component:

// index.js
function NameWithHandle() {
  return (
    <span className="name-with-handle">
      <span className="name">Your Name</span>
      <span className="handle">@yourhandle</span>
    </span>
  );
}

The CSS to style name and handle; added to our index.css is:

/* index.css */
.name {
  font-weight: bold;
  margin-bottom: 0.5em;
  margin-right: 0.3em;
}

.handle {
  color: #8899a6;
  font-size: 13px;
}

Next, let’s code the Time Component:

// index.js
const Time = () => <span className="time">3h ago</span>;

We can also construct simple components are variables set equal to an arrow function that returns JSX. As long as the JSX returned is valid, React don’t care if we use a variable or a regular function.

For Time we provide the following CSS in index.css:

/* index.css */
.time {
  padding-left: 0.3em;
  color: #8899a6;
}

.time::before {
  content: "\00b7";
  padding-right: 0.3em;
}

Next, we code our Button Components:

// index.js
const CommentButton = () => <i className="far fa-comment" />;
const RetweetButton = () => <i className="fa fa-retweet retweet-button" />;
const LikeButton = () => <i className="fa fa-heart like-button" />;
const ShareButton = () => <i className="fas fa-external-link-alt" />;

We can also construct simple components are variables set equal to an arrow function that returns JSX. As long as the JSX returned is valid, React don’t care if we use a variable or a regular function.

For Time we provide the following CSS in index.css:

/* index.css */
.button {
  margin-top: 10px;
  margin-left: 2px;
  font-size: 1.4em;
  color: #aab8c2;
}

.button i {
  width: 80px;
}

Finally, we modify our Tweet Component to use the new Components we just created. The final index.js looks like this:

// index.js
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";

function Tweet() {
  return (
    <div className="tweet">
      <Avatar />
      <div className="content">
        <NameWithHandle /> <Time />
        <Message />
        <div className="button">
          <CommentButton />
          <RetweetButton />
          <LikeButton />
          <ShareButton />
        </div>
      </div>
    </div>
  );
}

function Avatar() {
  return (
    <img
      src="https://gravatar.com/avatar/nothing"
      alt="avatar"
      className="avatar"
    />
  );
}

function Message() {
  return (
    <div className="message">This message is less than 140 characters!</div>
  );
}

function NameWithHandle() {
  return (
    <span className="NameWithHandle">
      <span className="name">Name</span>
      <span className="handle">@HandleName</span>
    </span>
  );
}

const Time = () => <span className="time">3h ago</span>;

const CommentButton = () => <i className="far fa-comment" />;
const RetweetButton = () => <i className="fa fa-retweet retweet-button" />;
const LikeButton = () => <i className="fa fa-heart like-button" />;
const ShareButton = () => <i className="fas fa-external-link-alt" />;

ReactDOM.render(<Tweet />, document.querySelector("#root"));

For our CSS styles, the final index.css looks like this:

/* index.css */
.tweet {
  border: 1px solid #cccccc;
  width: 564px;
  min-height: 68px;
  padding: 10px;
  display: flex;
  font-family: Arial, Helvetica, sans-serif;
  font-size: 14px;
  line-height: 18px;
}

.avatar {
  width: 48px;
  height: 48px;
  border-radius: 5px;
  margin-right: 10px;
}

.name {
  font-weight: bold;
  margin-bottom: 0.5em;
  margin-right: 0.3em;
}

.handle {
  color: #8899a6;
  font-size: 13px;
}

.time {
  padding-left: 0.3em;
  color: #8899a6;
}

.time::before {
  content: '\00b7';
  padding-right: 0.3em;
}

.button {
  margin-top: 10px;
  margin-left: 2px;
  font-size: 1.4em;
  color: #aab8c2;
}

.button i {
  width: 80px;
}

Tip: converting regular-functions to arrow-functions

React allows us the option of using variables to hold JSX components created using Arrow-Functions. Arrow functions are shorthand functions that automatically bind to the surrounding context (the this keyword in JavaScript). Arrow functions are extremely useful in many cases, especially where assigning to a variable or anywhere Anonymous Functions would normally be used such as in JavaScript callbacks in Promises or Async functions.
Let’s further explore Arrow functions by observing the transformation of a regular-function to an arrow-function. Consider our Time component.
To transform a function to a variable assigned an arrow-function follow four steps:

transform:

function Time() {
  return <span className="time">3h ago</span>;
}
  • Remove function keyword
  • Declare variable as const/let/var in front of function name removing ( )
  • Set variable = to empty ( ), space, => (arrow) followed by a space and the rest of the function as it looked previously
  • If arrow function contains only one expression then { } can be removed along with return statement as JavaScript treats this as an implicit return

to:

const Time = () => {
  return <span className="time">3h ago</span>;
};
to: (optional)
const Time = () => <span className="time">3h ago</span>;

In the next section we will look at how to make our React components more dynamic by using React Props.

 

Transcript

File & Base Setup

Welcome back. With our new found knowledge of components, let’s build a tweet to put that knowledge to the test.

The best way, I found, to build an application is to sketch out a rough draft before jumping into the deep end. A tweet consists of an avatar and or name, time, message, reply button, retweet button and more options button. For a simple hierarchy like this one, let’s start from the top down, basically, build the tweet component first, then it’s nested component.

To get started, create a new project with create React app by running this command in your terminal, npm initiate react-app static-tweet n cd static-tweet. Remember to do this in the directory that you would like to save all your applications. For me I’m saying it on my desktop in a folder called React. The second part of this command will take you right into the project directory once created.

The project was created with a few files we won’t use. Let’s go ahead and delete them with this command, rm src/App.* src/logo.svg src/registerServiceWorker .js. With that taken care of, open up the project in Visual Studio Code. Remember, file, open, then select the STATIC-TWEET folder.

You’ll notice here that the project has an index.html, we’ll need to add Font Awesome as a style sheet, this will allow us to use their icons for the buttons we’ll be creating Add Font Awesome by putting this line inside of the head tag.

Moving on, you’ll also see that in index.css file was generated in the source directory, open it up and replace its contents with this tweet class. This is just some basic CSS to give our tweets some style. Right now we’re only assigning a border of one pixel, solid, light gray color, a width of 564 pixels, the minimum height would be 68 pixels, padding around our border, 10 pixels, it’s going to be displayed flex, font family will be Helvetica, font size is 14 pixels and line height is 18 pixels.

Tweet Component

Next, let’s move on to our index.js file. The content here will be very similar to the one from HelloWorld.

So we’re going to go ahead and import our React from react, import ReactDom from react-dom and import our index.cs. Then write our Tweet function as we did our HelloWorld function before. And then we’re just gonna throw inside there Tweet print something out. Then we’re going to do our ReactDom.render and render our tweet component to root.

If you notice, we have two new elements in our component. First, we have a new import call that is import ./index.css which is importing a CSS file into a JavaScript file. What’s happening is that behind the scenes, when webpack builds our app, it sees this CSS import and learns that the index.js depends on index.css. Webpack reads the CSS file and includes it in the bundle JavaScript as a string to be sent to the browser.

Lastly, we add className equals tweet, which is the same as HTML class attribute used to define equal styles of element with the same class name. className value becomes the class attribution on the DOM node.

Now let’s run our application the same as before by opening our terminal in VS Code and typing in the command npm start. We get the bare bones. When we inspect the page using Google Developer Tools, look at the Elements tab and notice under Head, there’s a Style tag that we didn’t put there. It contains the content of index.css.

Let’s add some component. Next, we’ll need to build our avatar component. Shooting back over to index.js file, add function Avatar and that Avatar is going to return an image tag and in our image, we’re going to need a source. Our source is going to be https://www.gravtar.com/avatar/nothing and then our image also needs a className, which is going to equal avatar and then an alt that’s also going to equal avatar. The image tag is simple HTML. The only thing we are changing is class to className. For that, we’re going to use Gravtar to create our icon. Next, we’ll need to add the avatar component to our tweet.

So moving up to the tweet that we just created, we’ll add the avatar component. And just like that, our Tweet component is coming to life. Let’s give our avatar a bit of style. In the index.css file, add this class. And there you have it. Our tweet is slowly but surely coming together. See ya next time.

Final Details

So for our message component, we’re gonna do the same as we did for our tweet component. That message is going to return a div with a className of message and in between our div, we’re going to put this is less than 140 characters and then for our NameWithHandle component, we’re gonna change it up and that’s going to return a span with a className of NameWithHandle. And within that span, we’re going to have another span with a className of name, Your Name. Close that span and a secondary span at yourhandle. Close that span and close the initial span.

Now we need to add our recently created message and handle name components into our Tweet. So if we move up to our Tweet, we’ll add a div with a className of content. And inside of that div we’re going to put NameWithHandle component and our Message component.

And now shooting over to the index.css we’re going to add a bit of style to spruce up the look and feel. So we’re gonna add a name class and a handle class. Next up we’ll need to add the time and other button. We’re going to construct these a little differently than our previous components.

This component doesn’t look like the functions you’ve been writing up to this point but they are in fact still functions. They’re Arrow Function. These are shorthanded functions that automatically bind to the surrounding context. Here’s a progression from a Regular Function to an Arrow Function. So you can see what’s happening. Here’s a Normal Function component. It can then be written as an anonymous function and stored in a variable. It can then be simplified by removing the braces and the return.

Let’s finish up by creating our CommentButton, RetweetButton and ShareButton with Arrow Function. The eye tag that is within our button arrow functions is simple HTML for icon and the className is being pulled from Font Awesome. From here all we have to do now is add our time and our buttons within our tweet function and we are complete.

Let’s go ahead to the terminal and run our static tweet. We see that everything looks great. In the next lesson we’ll learn about props and how to make reusable components with props. See you next time.

Interested in continuing? Check out the full Bite-Sized React course, which is part of our Bite-Sized Coding Academy.

]]>
Creating a React and Reactstrap Card Gallery https://gamedevacademy.org/creating-a-react-and-reactstrap-card-gallery/ Fri, 10 Apr 2020 04:00:36 +0000 https://html5hive.org/?p=2120 Read more]]> For this tutorial, you will be utilizing React, npm, Node.js, Bootstrap, and Reactstrap. To keep all of the development environments static, I would advise everyone to use the same text editor like myself, Visual Studio Code, for this tutorial. If you are not familiar with React, I would recommend that you try this tutorial here first.

The purpose of this tutorial is to be able to familiarize oneself with React while creating a card game menu gallery.

Sill new to React? We recommend reviewing our articles on props and states to familiarize yourself with these concepts before jumping in!

Prerequisites: 

If you don’t have Node.js installed, I would recommend you install it from the source. If you do not have npm, I would recommend installing it for the source as well.

BUILD GAMES

FINAL DAYS: Unlock 250+ coding courses, guided learning paths, help from expert mentors, and more.

Once you have Node.js setup and npm, you will be able to install the other libraries through the terminal within Visual Studio Code terminal. Before we get into that, let’s have you create a folder and name it CARDUI once you have that built click terminal and open up a new terminal.

Type:

npm init

The npm init command will initialize creating a package.json file.

It will take you through several questions. You can leave everything defaults except for the entry point being index.html. Once you run through everything it will ask you if this is okay, answer yes.

Next run the following command, which will install the create-react-app:

npm install create-react-app

What is create-react-app?

Create-react-app lets you scaffold and quickly create React apps with no build configurations.

Run the following to create a new app, naming it cardui:

You will now need to change directories to cardui by typing the following in the terminal:

cd cardui/

Now we need to install two more libraries. Bootstrap and Reactstrap. Run the following commands in the terminal to install them.

npm install boostrap
npm install reactstrap

Now Open up the cardui folder and then open up the index.js file in the src folder and then add the following line into the imports:

import 'bootstrap/dist/css/bootstrap.min.css';

This adds a link to the Bootstrap CSS.

Components:

Now besides App.js we will be creating and using three more components in this React app. In addition to these three components, you will be utilizing two non-component JavaScript files that will be used to populate data for the cards and set filters to organize them by type. One of two additional non-component JavaScript files will be in JavaScript object notation, and the other one will be an array. We will export both.

Let’s start by having you create a new folder in the src folder named components and creating three new JavaScript files in there, CardInfo.js, Filter.js, and MainMenu.js. Then make another folder in the src folder named non-components and create two JavaScript filed named cards.js and filters.js. One last folder that you need to create is the images. Create that folder in the public folder. We will be using eight different images for this example supplied from opengameart.org. They are all under the CC0 license and are created by beouliin.

Open up filters.js and type in the following into it:

export const FILTERS = [
  'Fire',
  'Grass',
  'Water',
  'Mountains',
  'Air',
  'Rock',
  'Heart'
];

The const FILTERS will hold the types our cards can be, and this will be the filter attribute we will use to filter our card gallery.

Next, open up cards.js and type in the following into it:

export const CARDS = [
  {
    id: 0,
    name: "Red Monster",
    image: "images/id0.jpg",
    type: "Fire",
    attack: "5",
    damage: "5",
    description: "A monster from the volcanic region."
  },
  {
    id: 1,
    name: "Pink Monster",
    image: "images/id1.jpg",
    type: "Heart",
    attack: "4",
    damage: "2",
    description: "A monster from the heart region."
  },
  {
    id: 2,
    name: "Orange Monster",
    image: "images/id2.jpg",
    type: "Mountains",
    attack: "22",
    damage: "3",
    description: "A monster from the heart region."
  },
  {
    id: 3,
    name: "Blue Monster",
    image: "images/id3.jpg",
    type: "Water",
    attack: "1",
    damage: "13",
    description: "A monster from the water region."
  },
  {
    id: 4,
    name: "Green Monster",
    image: "images/id4.jpg",
    type: "Grass",
    attack: "3",
    damage: "1",
    description: "A monster from the grass region."
  },
  {
    id: 5,
    name: "Winged Monster",
    image: "images/id5.jpg",
    type: "Air",
    attack: "12",
    damage: "2",
    description: "A monster from the cloud region."
  },
  {
    id: 6,
    name: "Spiky Monster",
    image: "images/id6.jpg",
    type: "Rock",
    attack: "4",
    damage: "6",
    description: "A monster from the mountain region."
  },
  {
    id: 7,
    name: "Plant Monster",
    image: "images/id7.jpg",
    type: "Grass",
    attack: "8",
    damage: "4",
    description: "A monster from the jungle region."
  }
];

This will be the detailed information for the eight different types of cards we have. It doesn’t matter what the information in any of the portions is. These, json const variable and list const variable, are just a generic example to show you how to use a json and list within a React application. You can change anything you want and fiddle around with it, but if you make any changes to type you should make those changes to the FILTERS list as well because that is where the check and balances come into play later on.

Let us create an App.css. We will set the background color of the body and set a class type and set its background color as well. Normally you would set a variable within a component and set the properties for those elements within it, but this works just fine as well. It depends on how much you need to style, per component.

body {
  background-color: lightcyan;
}

.cardInfo {
  background-color: lightblue;
}

Here is an overview of the structure and file structure below. The first image is an outline of how the components relate to each and the second image is the file structure in my personal workplace.

As you can tell from the image below, it is a representation of the parents and child components and how each prop will be passed to its parent component.

Below is a representation of my personal work space. You should all have the same structure of folders and files, up to this point, if you are following along.

Now inside your cardui folder, open up the src folder and open up App.js.

Replace the original Class App Extends Component code with the following:

class App extends Component {
  render() {
    return (
      <div className="App">
        <MainMenu />
      </div>
    );
  }
}

Here we are replacing the standard code that comes with creating react app in App.js with our own which will render MainMenu only, as MainMenu will house all the other components.

FILTER.JS COMPONENT:

Now let’s open up the Filter.js file. You will be importing react components, Bootstrap card, and button components and the filter attribute list. Type in the following imports into it:

import React, { Component } from "react";
import { Card, CardImg, ButtonGroup, Button } from "reactstrap";
import { FILTERS } from "../non-components/filters";

The Filter component will render the all the card images and the side navigational filter. You will create two constant variable, card and filterButtons. The const cards will be a property that filters through the MainMenu state called cards for a specific type and maps individual keys to each card at rendering. Keys will be assigned using Math.random().toString(36).slice(2). There is a multitude of issues with generating keys in such a manner, but it will suit us perfectly fine for the scope of this tutorial. You can read more about the complexities of stringifying floating point numbers here.

The class of col-2 and m-1 will create a column of two and a margin of 1.

For the constant variable filterButtons, we will map the attribute types FILTERS from filters.js into a variable and use the fat arrow function to return a button that will have a key which will be the attribute type with an onclick event handler which will run a MainMenu method called cardFilterSelect, which updates the cardFilter state.

We use a combination of Reactstrap and Bootstrap for the quick scaffolding of the front-end. We use the Bootstrap classes for the grid and flexbox class elements and Reactstrap for the button and button groups.

It should look like the following:

class Filter extends Component {
  render() {
    const card = this.props.cards
      .filter(({ type }) => {
        return !this.props.filter || type === this.props.filter;
      })
      .map(card => {
        return (
          <div
            key={Math.random()
              .toString(36)
              .slice(2)}
            className="col-2 m-1"
          >
            <Card onClick={() => this.props.cardSelect(card.id)}>
              <CardImg src={card.image} alt={card.name} />
            </Card>
          </div>
        );
      });
    const filterButtons = FILTERS.map(filterName => {
      return (
        <Button
          key={filterName}
          onClick={() => this.props.cardFilterSelect(filterName)}
        >
          {filterName}
        </Button>
      );
    });

    return (
      <div className="container">
        <div className="row">
          <div className="col d-flex align-content-start flex-wrap">{card}</div>
          <div className="p-5 col-1">
            <ButtonGroup size="lg" vertical>
              <h6 style={{ color: "blue" }}>Card Attributes</h6>

              <Button onClick={() => this.props.cardFilterSelect(null)}>
                All
              </Button>
              {filterButtons}
            </ButtonGroup>
          </div>
        </div>
      </div>
    );
  }
}
export default Filter;
CARDINFO.JS COMPONENT:

Next open up CardInfo.js and import React and Reactstrap.

import React, { Component } from "react";
import { Card, CardImg } from "reactstrap";

The class CardInfo will extend Component and we will create two custom methods, then render the class out. The two methods that will be created are renderCard and renderInfo. Both will take a single parameter known as the card. RenderCard will return a card component with a card image and renderInfo will return a list of all the card information. We separate each item into a list item in an unordered list, assign headings and variables. Remember this component, CardInfo, will only render if it not null – which can be triggered by the Filter component.

class CardInfo extends Component {
  renderCard(card) {
    return (
      <Card>
        <CardImg src={card.image} alt={card.name} />
      </Card>
    );
  }

  renderInfo(card) {
    return (
      <ul className="list-unstyled">
        <li>
          <h6>Name :</h6>
          <div>{card.name}</div>
        </li>

        <li>
          <h6>Type : </h6>
          <div>{card.type}</div>
        </li>

        <li>
          <h6>Attack: </h6>
          <div>{card.attack}</div>
        </li>

        <li>
          <h6>Damage : </h6>
          <div>{card.damage}</div>
        </li>

        <li>
          <h6>Description : </h6>
          <div>{card.description}</div>
        </li>
      </ul>
    );
  }
  render() {
    const card = this.props.card;
    if (card != null)
      return (
        <div className=" cardInfo p-5 ">
          <div className="row">
            <div className="col-12 col-md-5 ">
              <p>hi</p>
              {this.renderCard(card)}
            </div>
            <div className="col-12 col-md-5 border border-primary">
              <h4>Card Information</h4>
              {this.renderInfo(card)}
            </div>
          </div>
        </div>
      );
    else return <div />;
  }
}

export default CardInfo;
MainMenu.JS COMPONENT:

Now I want you to go ahead and open up MainMenu.js. Here we will be creating and returning the navigational bar for our gallery as well as the Filter and CardInfo components and create several states that will be able to be lifted into the App.js file.

At the top import the following:

import React, { Component } from "react";
import { Navbar, NavbarBrand } from "reactstrap";
import Filter from "./Filter";
import CardInfo from "./CardInfo";
import { CARDS } from "../non-components/cards";

The first thing that gets called here is the constructor with the component props. We call super and pass props into it. Now we can start initializing the states and their default values within it.

Within the MainMenu class, we will create three states, cards for the CARDS const that we exported from the card.js, selectedCard which will be assigned the default value of null to and cardFilter which we will also assign null to. The states of these variables will change later as the application re-renders. For instance, selectedCard will change from null to the card.id that is selected.

class MainMenu extends Component {
  constructor(props) {
    super(props);

    this.state = {
      cards: CARDS,
      selectedCard: null,
      cardFilter: null
    };
  }

Now we will create two methods named cardSelect which will take cardId and cardFilterSelect which will take filterName. Both of these will use the setState to tell the components that it needs to be re-rendered and have its state updated.

  cardSelect(cardId) {
    this.setState({ selectedCard: cardId });
  }

  cardFilterSelect(filterName) {
    this.setState({ cardFilter: filterName });
  }

Next, we will render everything and export it out. In the render output we combine all the elements into one div. The Navbar is part of the Reactstrap library and makes up the Title in the Navigational Bar.

The Filer component creates the gallery of cards as well as the side bar navigation. Its cards state represents the current state of the cards json const variable from CARDS. The cardSelect uses the fat arrow function expression to assign the cardId its proper cardId when it re-renders during the setState of that method. The filter variable is assigned the cardFilter state and cardFilterSelect uses the fat arrow function expression to assign it the current filterName being used when it re-renders during the setState of that current method that is being used.

The CardInfo uses the filter() method check if it pass the test of card.id being equal to the selectedCard.

render() {
    return (
      <div>
        <Navbar dark color="primary">
          <div className="container">
            <NavbarBrand href="/" className="mx-auto">
              {" "}
              Card Selection Menu{" "}
            </NavbarBrand>
          </div>
        </Navbar>
        <Filter
          cards={this.state.cards}
          cardSelect={cardId => this.cardSelect(cardId)}
          filter={this.state.cardFilter}
          cardFilterSelect={filterName => this.cardFilterSelect(filterName)}
        />
        <CardInfo
          card={
            this.state.cards.filter(
              card => card.id === this.state.selectedCard
            )[0]
          }
        />
      </div>
    );
  }
}

export default MainMenu;

For more information about Reactstrap, I personally recommend looking over Bootstrap and Reactstrap. They are well documented libraries, Bootstrap more so than Reactstrap.

The final product should look something similar or along the lines as the following screenshot. You download the source code here.

Thanks for following along with this tutorial. Please feel free to leave your comment below if there are any thoughts that you’d like to share.

]]>
Create a Card Game in Canvas with React Components https://gamedevacademy.org/create-a-card-game-in-canvas-with-react-components/ Wed, 14 Aug 2019 15:00:34 +0000 https://html5hive.org/?p=2209 Read more]]> What’s a website without a little fun and games now and then?  Even if you’ve never made a game before, or have no experience with game engines like Unity, that’s okay! Instead, you can channel the power of React Components and put your web development knowledge to work adding some fun aspects to your website.

This tutorial’s project will revolve around utilizing React, Canvas, and the create-react-app in React to create a simple card game called War. It’s recommended that you have some basic beginner experience with Canvas and React before delving in. As in additional note, I will be using Visual Studio Code throughout this whole project, and you can utilize that as a reference for the rest of the code and images below.

The source code is for the project can be found here! Also, be sure to check out this refresher course on props and states before getting started!

BUILD GAMES

FINAL DAYS: Unlock 250+ coding courses, guided learning paths, help from expert mentors, and more.

Overview of the Game Setup

If you’ve never played War as a child, it is a simple game with a simple objective: win all the cards. The deck is divided evenly amongst the players, given to them with the card facing down. Each player will reveal their top card at the same time. The player who has the highest card takes both cards and moves them to the bottom of their stack. If two cards are played of equal value, then both players will keep playing cards down until one of the players has a higher card then the other. Then that winner takes all the cards again and places them at the bottom of his stack. The player with no cards left loses. We will use one big React component with methods and functions to create it.

Quick Overview: What is Canvas?

HTML canvas is an HTML element that is utilized to draw graphics and animate them. This can be used for anything from cartoon animation, video game design and/or graphical user interface animation.

Quick Overview: What is create-react-app?

Create-react-app is a tool that will give you a prebuild react workspace. It helps you utilize your time more efficiently by giving you a foundation to work with. You import the foundation that you will be working with one simple command.

Installing Create React App

Open your terminal window. You can do this by clicking Terminal at the top and then New Terminal. Then type:

npm install create-react-app

This will install the create-react-app tool and all its dependencies. Once it’s installed you will go ahead and run the following command to create a new React project and the name the project:

Create-react-app war-game

In the above code, war-game would be the name of the project we will be making but it can be named anything you would like but I named it war-game for this project as the game is based on the card game called War.

Now let’s move into the project folder by typing:

war-game

Now you can start the live development server that will automatically update anytime you make changes by using the following command:

npm start

Editing your folder structure.

We are going to need to make a few changes in your folder structure. Open up src in the war-game folder and create a images folder.

Images folder as seen in src folder

Here is where we will be uploading the three images we will be using for our project.

Various war game card images in images folder

Let’s go into our App.css folder which will be out main CSS for our main component and change a few of the standard settings that have been put in place for us with the create react app. Your current folder should look like the following:

.App {
  text-align: center;
}

.App-logo {
  animation: App-logo-spin infinite 20s linear;
  height: 40vmin;
  pointer-events: none;
}

.App-header {
  background-color: #282c34;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  font-size: calc(10px + 2vmin);
  color: white;
}

.App-link {
  color: #61dafb;
}

@keyframes App-logo-spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

Let’s go over some of the CSS properties used in the class above. The property animation is being used with the @keyframes keyword to create rules and define how the animation will act. It’s a very useful property to help allow yourself to create CSS animations.

Pointer events property controls how the internal HTML will react to the cursor interacting with it. For instance in the property above its defined as none, which means that it will prevent all types of clicks and cursor option associated with that specific class.

Remove everything under the App class brackets and create a new class called App-body. It should like this now:

.App {
  text-align: center;
}

.App-body {
  background-color: #687186;
  min-height: 100vh;
  min-width: 400px;
  max-width: 800px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  font-size: calc(10px + 2vmin);
  color: white;
}

Once you have done that let’s go ahead and save it. We will use that App-body class later on. Now one more quick change that must be made is with the App.js file. Your current file  should look like the following:

import React from 'react';
import logo from './logo.svg';
import './App.css';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code> src/App.js </code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

Let’s open that up and just quickly replace the original imports at the top with the following:

import React from 'react';
import './App.css';
import WarGame from './WarGame.js';

We do this because we don’t need the logo and won’t be using it and we will be importing a new component that we will be making, which will hold the main game called WarGame.

Now let’s restructure the function App by just having it contain two div containers. One with the App class and the other with the App-body class that we recently made. In between those two, we will put our WarGame component.

function App() {

  return (
    <div className="App">
      <div className="App-body">
      <WarGame> </WarGame>
      </div>
    </div>
  );
}

export default App;

The main component WarGame:

Create a new JavaScript file named WarGame and create a new CSS file named WarGame. We will add the styling of the WarGame CSS and then finish it up with the JavaScript component.

Open up the WarGame.css file and create the following classes:

  • CardTable
  • CardTableHeader
  • HeaderText
  • CardTableMainArea
  • CardTableFooter
  • TableCanvas
  • HiddenImage

All these classes will have simple stylings.

.CardTable{
    background-color: rgb(116, 164, 236);
    max-height: 600px;
    height: 500px;
    min-width: 400px;
    width: 500px;

}

What does it do?

CardTable will be the class that will be in the div encapsulating the game.

.CardTableHeader{
    display: table;
    background-color: rgb(156, 165, 179);
    height: 48px;
    width: 100%;
}

What does it do?

CardTableHeader will be associated with the Card Count for the AI and the player, as well as the button.

.HeaderText{
    display: inline-block;
    width: 33%;
}

What does it do?

HeaderText will be the class styling of the Player and AI text stating how many cards they have.

.CardTableMainArea{
    overflow: hidden;
    background-color: rgb(102, 202, 110);
    height: 500px;
    width: 500px;
}

What does it do?

CardTableMainArea will be the main class that will reside in the outer div incapsulating the canvas.

.CardTableFooter{
    height: 48px;
    background-color: azure;
}

What does it do?

CardTable will be the class that will be in the div encapsulating the game.

.TableCanvas{
    height: 500px;
    width: 500px;
}

What does it do?

TableCanvas will be the main styling for the actual canvas.

.HiddenImage{
    display: none;
}

What does it do?

Hidden Image will not display anything.

Next, we have the WarGameButton and its pseudo-classes for hover and active.

.WarGameButton {
    -moz-box-shadow:inset 0px 1px 0px 0px #ffffff;
    -webkit-box-shadow:inset 0px 1px 0px 0px #ffffff;
    box-shadow:inset 0px 1px 0px 0px #ffffff;
    background:-webkit-gradient(linear, left top, left bottom, color-stop(0.05, #ffffff), color-stop(1, #f6f6f6));
    background:-moz-linear-gradient(top, #ffffff 5%, #f6f6f6 100%);
    background:-webkit-linear-gradient(top, #ffffff 5%, #f6f6f6 100%);
    background:-o-linear-gradient(top, #ffffff 5%, #f6f6f6 100%);
    background:-ms-linear-gradient(top, #ffffff 5%, #f6f6f6 100%);
    background:linear-gradient(to bottom, #ffffff 5%, #f6f6f6 100%);
    filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f6f6f6',GradientType=0);
    background-color:#ffffff;
    -moz-border-radius:6px;
    -webkit-border-radius:6px;
    border-radius:6px;
    border:1px solid #dcdcdc;
    display:inline-block;
    cursor:pointer;
    color:#666666;
    font-family:Arial;
    font-size:15px;
    font-weight:bold;
    padding:6px 24px;
    text-decoration:none;
    text-shadow:0px 1px 0px #ffffff;
}
.WarGameButton:hover {
    background:-webkit-gradient(linear, left top, left bottom, color-stop(0.05, #f6f6f6), color-stop(1, #ffffff));
    background:-moz-linear-gradient(top, #f6f6f6 5%, #ffffff 100%);
    background:-webkit-linear-gradient(top, #f6f6f6 5%, #ffffff 100%);
    background:-o-linear-gradient(top, #f6f6f6 5%, #ffffff 100%);
    background:-ms-linear-gradient(top, #f6f6f6 5%, #ffffff 100%);
    background:linear-gradient(to bottom, #f6f6f6 5%, #ffffff 100%);
    filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f6f6f6', endColorstr='#ffffff',GradientType=0);
    background-color:#f6f6f6;
}
.WarGameButton:active {
    position:relative;
    top:1px;
}

If you look at the properties in the classes above you might be asking yourself what all these -moz and -webkit properties are for the classes. Well, they are called vendor prefixes but also referred to as browser prefixes at times. Prefixes were and still are used when a certain browser doesn’t support the full functionality of certain CSS modules. You can use those capabilities and support them right away with the use of prefixes and not have to worry about different browser not working or waiting on browser manufacturers to catch up.

The major browsers use the following prefixes:

  • -webkit-(Chrome, Safari, newer versions of Opera, almost all iOS browsers)
  • -moz-(Firefox)
  • -o-(Old versions of Opera)
  • -ms-(Internet Explorer/Microsoft Edge)

Open up WarGame.js and in the imports import React Component, WarGame.css and two different images, deck and cover.

import React, { Component } from 'react';
import './WarGame.css';
import CadrDeckImage from './images/deck.png';
import CadrCover from './images/cover.png';

Create a class for the file named WarGame and it will extend Component. Remember that the main class name will always be the same as the file it is in.

class WarGame extends Component {
    constructor(props)
    {
        super(props);
     

Quick Overview: Constructors?

A constructor is a method that gets called during the creation of the class, for this project it would be the WarGame class. It would automatically get called before the component is mounted.

Quick Overview: Super()?

Super refers to its parent class, the constructor class. You also can’t use this in a constructor until after you’ve called it. So if you want to use this.state you need to specify super and pass the props to it.

Create a constructor, super and then we will need to create a few different states.  You’ll need a few states associated with the players, the AI, the Cards themselves and the game state. You will also need to set a few binding states.

        this.state = {AppMode: 'NoAction',  // NoAction, Game, PlayerWin, AIWin
                    MoveState: 'NoState', 
                    CardsDeck: new Array(52),
                    PlayerDeck: new Array(52),
                    AIDeck: new Array(52),
                    PlayerBank: new Array(52),
                    AIBank: new Array(52),
                    MoveCount: 0

        };
        this.TableCanvas = React.createRef()

        // binding for set this
        this.StartNewGame.bind(this);
        this.DoOneMove.bind(this);
        this.EndMove.bind(this);
        this.GetOneCardFromDeck.bind(this);
        this.componentDidUpdate.bind(this);
        this.render.bind(this);
        this.draw_card.bind(this);
      
  }

Now we will need to create the animation to this meat and bones of this program, thankfully that’s what javascript is for. We will write up the rest of the javascript methods, the methods that will be running the cogs for us and that will make sense of all these binding and set states. It’s good to get a broad understanding of the structure and functionality of the project we are working on before moving forward with it. The following is a break down of methods that we will be making and what they will be doing:

  • GetOneCardFromDeck: Will get a card from the deck.
  • MoveDeck: Removes one card from the deck.
  • GetCardCount: Get’s the card count of the cards in the deck at the time of running.
  • StartNewGame: This will initialize the program and start a new game, as well as clearing and randomizing the AI & player decks.
  • DoOneMove: DoOneMove will be our card check state management system.  It will control whether the cards match, they don’t match or neutral.
  • EndMove: In end move, we will check the scores between the AI and the player to see who wins.
  • componentDidUpdate: This will update all the canvas content on the screen
  • draw_card: This will move the cards that are drawn to the middle of the screen.
  • BtnOnMoveClick: This will handle the event handler and call the method DoOneMove and changes the sate of MoveCount by one. Then we return everything in their appropriate divs.

Let’s move onto making the first three methods of the card game. Use GetOneCardFrom deck and create an anonymous function that will either return a random number with 52 being maxed or return a count of the cards if no card is present/state that there is no card left.

GetOneCardFromDeck = () =>{
    let rnd = Math.round(Math.random() * 52);
    if(this.state.CardsDeck[rnd] != 0){
      this.state.CardsDeck[rnd] = 0;
      return rnd;
    }
    // This card is absent! - We need get next one
    for(let count = rnd + 1; count < 52; count ++){
      if(this.state.CardsDeck[count] != 0){
        this.state.CardsDeck[count] = 0;
        return count;
      }
    }
    // let's look down
    for(let count = rnd - 1; count >= 0; count --){
      if(this.state.CardsDeck[count] != 0){
        this.state.CardsDeck[count] = 0;
        return count;
      }
    }
    // If we are here - no cards in deck!
    return - 1;
  }

Moving onto MoveDeck we will create an anonymous function with an argument of the deck that will remove one card from the deck.

MoveDeck = (deck) =>{
  for(let count = 0; count < 51; count ++){
    deck[count] = deck[count + 1];
  }
  deck[51] = null;
}

GetCardCount will take a parameter of the deck like above but will return the number of cards in the deck.

GetCardCount = (deck) =>{
  let count;
  for(count = 0; count < 52; count ++){
    if(deck[count] == null){break};
  }
  return count == 52 ? 0:  count ++;
}

StartNewGame will initialize the game and fill both decks for AI and the player. It will then set the state of MoveState and AppMode.

  StartNewGame = () =>{
    // Init new Game
    // Fill deck of cards and clearing AI & players decks
    for(let count = 0; count < 52; count ++){
        this.state.CardsDeck[count] = 1;
        this.state.PlayerDeck[count] = null;
        this.state.AIDeck[count] = null;
        this.state.PlayerBank[count] = null;
        this.state.AIBank[count] = null;
      
    }
    // now get random item and pass it to player or AI
    for(let count = 0; count < 26; count ++){
      this.state.PlayerDeck[count] = this.GetOneCardFromDeck();
      this.state.AIDeck[count] = this.GetOneCardFromDeck();
    }
    this.setState({MoveState: 'NoState'});
    this.setState({AppMode:   'Game'});
        
  }

DoOneMove will be a method with a switch case for the MoveState.

  DoOneMove = () =>{
// There are 2 options:
// 1. Banks is empty. Need to put one card
// 2. Banks is NO empty. Need to put three cards + one
  let PlayerCard = -1;
  let AICard = -1;
  let BankCardCount;
  let PlayerCount = 0;
  let AICardCount = 0;

    switch(this.state.MoveState){
      case 'Equality':
        // 2-nd option  
        // Here we need to check - is there enough cards.
        PlayerCount = this.GetCardCount(this.state.PlayerDeck);
        AICardCount = this.GetCardCount(this.state.AIDeck);
        if(PlayerCount < 4){
          this.state({AppMode: 'AIWin'});
        }
        if(AICardCount < 4){
          this.state({AppMode: 'PlayerWin'});
        }

        // Put 3 cards + 1 to the bank
        BankCardCount = this.GetCardCount(this.state.PlayerBank);
        for(let count = 0; count < 4; count ++){
            PlayerCard = this.state.PlayerDeck[0];
            AICard     = this.state.AIDeck [0];
            this.MoveDeck(this.state.PlayerDeck);
            this.MoveDeck(this.state.AIDeck);
            this.state.PlayerBank[BankCardCount] = PlayerCard;
            this.state.AIBank[BankCardCount]     = AICard;

            BankCardCount ++;
        }

        if((PlayerCard % 13) == (AICard % 13)){
            this.setState({MoveState: 'Equality'});
          }
        else
        {
          this.setState({MoveState: 'EndMove'});
        }
  
        
        break;
      case 'EndMove':
        this.EndMove();
        this.setState({MoveState: 'NoState'});
        break;
      case 'NoState':
      default:
        // 1-st option
        PlayerCard = this.state.PlayerDeck[0];
        AICard     = this.state.AIDeck [0];
        this.MoveDeck(this.state.PlayerDeck);
        this.MoveDeck(this.state.AIDeck);
        
        BankCardCount = this.GetCardCount(this.state.PlayerBank);
        console.log(BankCardCount);
        this.state.PlayerBank[BankCardCount] = PlayerCard;
        this.state.AIBank[BankCardCount]     = AICard;

        if((PlayerCard % 13) == (AICard % 13)){
          // 
          this.setState({MoveState: 'Equality'});
        }else{
          this.setState({MoveState: 'EndMove'});
        }
        break;

    }
  }

EndMove will decide whether we have a winner or loser or if our cards are the same as the ai.

  EndMove = () =>{
    // End move
    let BankCardCount = this.GetCardCount(this.state.PlayerBank);
    let PlayerCard = this.state.PlayerBank[BankCardCount - 1] % 13;
    let AICard = this.state.AIBank[BankCardCount - 1] % 13;
    let count;
    let AICardCount;
    let PlayerCardCount;
    
    if(PlayerCard == AICard){
      // Do nothing. We can't here!!!
    }else
    {
      if(PlayerCard > AICard)
      {
        // Player win!
        // move cards to players deck
        console.log('Player win!');
        PlayerCardCount = this.GetCardCount(this.state.PlayerDeck);
        for(count = 0; count < BankCardCount; count ++)
        {
          this.state.PlayerDeck[PlayerCardCount] = this.state.PlayerBank[count];
          this.state.PlayerBank[count] = null;
          PlayerCardCount ++
        }
        for(count = 0; count < BankCardCount; count ++)
        {
          this.state.PlayerDeck[PlayerCardCount] = this.state.AIBank[count];
          this.state.AIBank[count] = null;
          PlayerCardCount ++
        }
        // Chek AI deck
        AICardCount = this.GetCardCount(this.state.AIDeck);
        if(AICardCount == 0){
          this.setState({AppMode: 'PlayerWin'})
        }
      }
      else
      {
      // AI win!
        // move cards to AI deck
        console.log('AI win!');
        AICardCount = this.GetCardCount(this.state.AIDeck);
        for(count = 0; count < BankCardCount; count ++)
        {
          this.state.AIDeck[AICardCount] = this.state.AIBank[count];
          this.state.AIBank[count] = null;
          AICardCount ++
        }
        for(count = 0; count < BankCardCount; count ++)
        {
          this.state.AIDeck[AICardCount] = this.state.PlayerBank[count];
          this.state.PlayerBank[count] = null;
          AICardCount ++
        }
        // Chek Player deck
        AICardCount = this.GetCardCount(this.state.PlayerDeck);
        if(AICardCount == 0){
          this.setState({AppMode: 'AIWin'})
        }
      }
    }
  }

ComponentDidUpdate will update our canvas and draw it with images of the cards.

  componentDidUpdate(){
      let TableCtx = this.refs.TableCanvas.getContext("2d");
    let count;

      TableCtx.fillStyle = "green";
      TableCtx.fillRect(0, 0, 500, 500);

      // Draw current scene
      // 1. Player and AI Deck
      let CardsInDeck = Math.floor(this.GetCardCount(this.state.AIDeck) / 13);
      TableCtx.drawImage(this.refs.CadrCover, CardsInDeck * 70, 0, 70, 96, 50, 30, 70, 96);

      CardsInDeck = Math.floor(this.GetCardCount(this.state.PlayerDeck) / 13);
      TableCtx.drawImage(this.refs.CadrCover, CardsInDeck * 70, 0, 70, 96, 300, 350, 70, 96);


      //2. banks

    let CardsInBank = this.GetCardCount(this.state.PlayerBank);
    console.log('Cards in player bank - ' + CardsInBank);

    //players bank
    let bc_x = 300;
    let bc_y = 200;

    for(count = 0; count < CardsInBank; count ++)
    {
        if(count % 4 == 0)
        {
          this.draw_card(this.state.PlayerBank[count], bc_x, bc_y);
          this.draw_card(this.state.AIBank[count], bc_x - 200, bc_y);
        }
        else
        {
          this.draw_card(-1, bc_x, bc_y);
          this.draw_card(-1, bc_x - 200, bc_y);
        }
        bc_x += 16;
        bc_y += 16;
    }
  }

draw_card will move the card on the canvas and draw it.

draw_card(CardNumber, DestinationX, DestinationY){

    let TableCtx = this.refs.TableCanvas.getContext("2d");

    if(CardNumber == -1)
    {
      TableCtx.drawImage(this.refs.CadrCover, 6, 0, 64, 96, DestinationX, DestinationY, 64, 96);
      
    }
    else{
      // size of 1 card in image at tis time: 64*96
      let SourceX = (CardNumber % 13) * 64;
      let SourceY = Math.floor(CardNumber / 13) * 96;

      TableCtx.drawImage(this.refs.CadrDeckImg, SourceX, SourceY, 64, 96, DestinationX, DestinationY, 64, 96);
    }

  }

BtnOnMoveClick will be an anonymous function that will handle our event handling for MoveCount state.

BtnOnMoveClick = event => {
    this.DoOneMove();
    this.setState({ MoveCount: this.state.MoveCount + 1 });
  };

Render will render everything back into the DOM.

  render = () => {
    let BtnText = "Move";
    switch (this.state.MoveState) {
      case "EndMove":
        // Someone will win! Let's chek it
        let BankCardCount = this.GetCardCount(this.state.PlayerBank);
        let PlayerCard = this.state.PlayerBank[BankCardCount - 1] % 13;
        let AICard = this.state.AIBank[BankCardCount - 1] % 13;
        if (PlayerCard > AICard) {
          BtnText = "Player WIN!";
        } else {
          BtnText = "AI WIN!";
        }
        break;
      case "Equality":
        BtnText = "WAR! - next step";
        break;
      default:
        BtnText = "Move";
        break;
    }

    let AICardCount = this.GetCardCount(this.state.AIDeck);
    let PlayerCardCount = this.GetCardCount(this.state.PlayerDeck);
    //
    return (
      <div className="CardTable">
        <div className="CardTableHeader">
          <div className="HeaderText"> AI ({AICardCount}) </div>

          <button
            className="WarGameButton HeaderText"
            onClick={this.StartNewGame}
          >
            {" "}
            New game{" "}
          </button>

          <div className="HeaderText"> Player ({PlayerCardCount}) </div>
        </div>
        <div className="CardTableMainArea">
          <canvas
            ref="TableCanvas"
            className="TableCanvas"
            width={500}
            height={500}
          />
        </div>
        <div className="CardTableFooter">
          {this.state.AppMode == "Game" ? (
            <button
              className="WarGameButton"
              onClick={this.BtnOnMoveClick.bind(this)}
            >
              {" "}
              {BtnText}{" "}
            </button>
          ) : (
            this.state.AppMode
          )}
        </div>

        <img
          ref="CadrDeckImg"
          className="HiddenImage"
          src={CadrDeckImage}
          alt="deck"
        />
        <img
          ref="CadrCover"
          className="HiddenImage"
          src={CadrCover}
          alt="deck"
        />
      </div>
    );
  };
}
export default WarGame;

Now just type npm start in your terminal if you don’t have it up and you should have the project up and working perfectly!

War card game built with Canvas and React

And there you have it!  You now have your very own war card game built only with Canvas and React Components.  Though you can certainly improve upon it, it’s a great start to adding more spice to your websites (or to pass the time).

]]>
Understanding React.js Higher-Order Components https://gamedevacademy.org/understanding-react-js-higher-order-components/ Wed, 03 Apr 2019 04:00:11 +0000 https://html5hive.org/?p=2059 Read more]]> In this tutorial, we will approach React.js Higher-Order Components (HOCs), with the help of an easy to understand, basic example. To follow along, you will need some React.js and JavaScript knowledge, but everything is detailed in the checklist below.

Download the source code

You can follow along, and build your app from the ground up, or better yet, you can download the files used in the tutorial from here.

BUILD GAMES

FINAL DAYS: Unlock 250+ coding courses, guided learning paths, help from expert mentors, and more.

Before moving forward

Note that after downloading the files, to get the app running you will have to navigate to the project folder: cd my-hoc and install the dependencies by running npm install  in your terminal.

What will you need – checklist

  • Basic knowledge of React.js and JavaScript (ES6 Arrow Functions). You can check out the Beginner’s Guide to React.js with examples tutorial, or the Build Web Apps with React JS and Flux course, which covers everything you need, and more. If you have a basic knowledge of React.js and want to continue your learning journey by adding more complex patterns/concepts to your tool-belt, then this article is for you! We will use an easy example of HOCs to get you familiar with the possibilities, which you can later apply to your more advanced projects.
  • Text editor of your choice. Some popular text editors are Atom, Sublime Text, Notepad++. Syntax highlighting is a plus.
  • To get started quickly, we will use create-react-app, which handles the creation of all our starter files, so we can focus on development faster. If you wish to follow along, make sure to have Node.js >= 6 on your local development machine and npm  installed, as this is a requirement for the create-react-app .

What are Higher-Order Components (HOCs) ?

Basically, a Higher-Order Component (HOC) is a function that takes a component as an argument, and returns another component. The returned component is not any kind of component, it’s a component with superpowers (sadly not the kind of superpowers we all wish we had when we were kids), so to say.
It’s actually that simple! ????

Note from The React docs:

HOCs are not part of the React API, per se. They are a pattern that emerges from React’s compositional nature.

Higher-Order Components are a powerful pattern, for providing and fetching data to other components.

When can we use Higher-Order Components (HOCs) ?

Whenever we want to wrap a repeating pattern. Also, having repeating code with a lot of functionality would be difficult to maintain in larger applications.

However it’s best not to overuse them – and always check if another pattern could be more appropriate.

That being said, let’s get started!

We will begin by bootstrapping our project with create-react-app . Let’s open up our terminal window, and run:

npx create-react-app my-hoc

You can also use npm init , which is available in npm > 6

npm init react-app my-hoc

Or if you prefer Yarn

yarn create react-app my-hoc

 

This will create the my-hoc  folder, with our initial project structure.

Once the installation is completed, still in our terminal, we will navigate to the project folder: cd my-hoc

And start the development server with npm start .

Note: If you are using Yarn, you can run yarn start .

A new browser page should open, but if it doesn’t, navigate to http://localhost:3000/  to see your app running.

App initial page

Our initial project structure will look like this:

App initial folder structure

Now, let’s do some cleaning. We will remove the logo and the generated boilerplate code, and also replace the starter css  with our own styles.

The files that we’ll modify are App.js  and App.css , which after refactor, will look like this:

App.js  file:

import React, { Component } from 'react'
import './App.css'

class App extends Component {
  render() {
    return (
      <div className="App">

      </div>
    )
  }
}

export default App;

App.css  file:

.App {
  display: flex;
  border: 1px solid #000;
  margin: 25px auto;
  padding: 25px;
  max-width: 750px;
}

.score-panel {
  display: flex;
  flex-direction: column;
  align-items: center;
  border: 10px solid lightblue;
  width: 70%;
}

.player-info {
  display: flex;
  flex-direction: column;
  border: 1px solid #000;
  border-radius: 15px;
  margin: 5px;
  padding-left: 15px;
  width: 30%;
}

We won’t do more styling for this particular example, but feel free to unleash your inner artist and add an awesome look to the application as we build our components. ????

What will we build ?

Let’s say that we have a game, and that we want some of the player information, such as the player name and player score, to be displayed in our page.
We will want the name and score to be displayed in two places, in the score panel, and in the player card.

In future articles, we will look into how to build/use an API to store our player data, as well as building a game, but for now, for the simplicity of our example, we will hard-code the data in a separate file.

In our project src  folder, we will create a new file, data.js , which will store and export our playerData .

data.js  file:

const playerData = {
  name:  'Johnny Doey',
  score: 'over 9000'
}

export default playerData

While we’re here, in the src  folder, let’s go ahead and create another folder, components , which will hold our PlayerInfo  and ScorePanel  components, that will get and display the player data. Let’s give them some code!

PlayerInfo.js  file:

import React, { Component } from 'react'
import playerData from '../data.js'

export default class PlayerInfo extends Component {
  constructor(props) {
    super(props);

    this.state = {
      name: "Welcome back...",
      score: "Calculating..."
    }
  }

  componentDidMount() {
    this.setState({
      name: playerData.name,
      score: playerData.score
    })
  }

  render() {
    return(
      <div className="player-info">
        <p>Name: { this.state.name }</p>
        <p>Score: { this.state.score }</p>
      </div>
    )
  }
}

ScorePanel.js  file:

import React, { Component } from 'react'
import playerData from '../data.js'

export default class ScorePanel extends Component {
  constructor(props) {
    super(props);

    this.state = {
      name: "Welcome back...",
      score: "Calculating..."
    }
  }

  componentDidMount() {
    this.setState({
      name: playerData.name,
      score: playerData.score
    })
  }

  render() {
    return(
      <div className="score-panel">
        <h2>{ this.state.name }</h2>
        <p>{ this.state.score }</p>
      </div>
    )
  }
}

In both components, we’ve imported the playerData  from our data.js  file.
We’ve defined the state  with some initial values, and in the componentDidMount  life-cycle method we’ve set the state to the playerData  values.

The componentDidMount  life-cycle method is available after the component has mounted, after the HTML from render has completed its loading. It is called once in the component life-cycle, and it signals that the component and all of its sub-components have rendered properly.
This is the place where we can do anything that we want to set up in the DOM, such as API calls.

Moving forward, let’s make use our newly created components, by including them in the App.js  file.

import React, { Component } from 'react'
import './App.css'
import PlayerInfo from './components/PlayerInfo'
import ScorePanel from './components/ScorePanel'

class App extends Component {
  render() {
    return (
      <div className="App">
        <ScorePanel />
        <PlayerInfo />
      </div>
    );
  }
}

export default App

The results displayed on the screen:

Render result before adding a Higher-Order Component

And our folder structure will be:

Project file structure before Higher-Order Component (HOC)

But wait a second…let’s take a second look at our PlayerInfo  and ScorePanel  components.
In both of them we are getting the playerData , setting their state to the desired values, and returning something that will be rendered.

Déjà vu ? Repeating patterns ? It’s HOC Time!

As mentioned at the beginning of this article, in React, a HOC is a function that takes a component as an argument, and returns another component with superpowers.

By doing so, we can break our application into simple and reusable functions.

To put this into practice…

We will create our HOC in a new file, withPlayerData.js . The naming convention is to use with  as a prefix for the HOC, to describe the returning superpower.
This makes code maintenance  much easier, as well as finding bugs faster . Also, it will help the reader to understand the code logic easily.

In our withPlayerData.js  file:

import React, { Component } from 'react'
import playerData from '../data.js'

const withPlayerData = WrappedComponent =>
  class extends Component {
    constructor(props) {
      super(props)

      this.state = {
        name: "Welcome back...",
        score: "Calculating..."
      }
    }

    componentDidMount() {
      this.setState({
        name: playerData.name,
        score: playerData.score
      })
    }

    render() {
      return(
        <WrappedComponent
          playerName={this.state.name}
          playerPoints={this.state.score}
          {...this.props} />
      )
    }
  }

export default withPlayerData

Again, we are importing React  and our playerData.

Next, we define our withPlayerData  function, which takes WrappedComponent  as an argument.

Then, we have the constructor with our state, which stores the name  and score  of our player, the componentDidMount  life-cycle method, that we will use to get our player name  and score  from the data.js  file, and last but not least, the render method. So basically we’ve moved the repeated logic from the other two components into this one.

In the render methods return statement, we have our initial argument – the WrappedComponent .
This WrappedComponent  has our props:

playerName={this.state.name} 
playerPoints={this.state.score}

And it’s receiving the source components props from {…this.props} .

 

What does {…this.props}  actually do.

It’s called spread attribute, and it makes the passing of props easier.
Imagine that later on, we will want to add more player data such as unlockables, skins, stats, skills, currency and so on. If you have a component that accepts a number of props, passing them down can be overwhelming and tedious when/if their number grows. Taking this into account, instead of passing props like this:

<OurComponent foo={} bar={} baz={} lorem={} ipsum={} kitty={} />

We can simply wrap them up in an object and use the spread notation to pass them to our component: <OurComponent {…props} /> , and in OurComponent , we can then use the props normally.

 i.e

this.props.foo
this.props.bar
this.props.baz
this.props.lorem
this.props.ipsum
this.props.kitty

Back to our withPlayerData  HOC, in which we have now created a reusable provider for the player data!

Refactoring our application…

…to make use of the newly acquired superpower, Higher-Order Component.

In our ScorePanel  and PlayerInfo  files, we’ll first remove the playerData , and import our withPlayerData  HOC, to make use of it.

ScorePanel.js  file:

import React, { Component } from 'react'
// import playerData from '../data.js'
import withPlayerData from './withPlayerData'

Next, let’s remove the constructor , state , and componentDidMount  life-cycle method.

Because we have moved all the functionality to our HOC, our component only needs to render, so we can use a functional component instead of a Class component.

A functional component is just a JavaScript function which accepts an argument(props), and returns a React element. They are useful for presentational components which focus on the UI, rather than on behaviour.

So why use a functional component?!

  • Because it’s easier to read
  • Because it’s easier test
  • Because it’s less code

The resulting, refactored functional component:

const ScorePanel = ({playerName, playerPoints}) => (
  <div className="score-panel">
    <p className="user-name">{ playerName } <span>({ playerPoints })</span></p>
  </div>
)

And to use our HOC, we just have to export it with our component passed in as an argument:

export default withPlayerData(ScorePanel)

Finally, our ScorePanel  components new look:

import React from 'react'
import withPlayerData from './withPlayerData'

const ScorePanel = ({playerName, playerPoints}) => (
  <div className="score-panel">
    <h2>{ playerName }</h2>
    <p>{ playerPoints }</p>
  </div>
)

export default withPlayerData(ScorePanel)

Nice, clean and simple.

Applying the same refactor in the PlayerInfo.js  component:

import React from 'react'
// import playerData from '../data.js'
import withPlayerData from './withPlayerData'

// export default class PlayerInfo extends React.Component {
//   constructor(props) {
//     super(props);
//
//     this.state = {
//       name: "Welcome back...",
//       score: "Calculating..."
//     }
//   }
//
//   componentDidMount() {
//     this.setState({
//       name: playerData.name,
//       score: playerData.score
//     })
//   }
//
//   render() {
//     return(
//       <div className="player-info">
//         <p>Name: { this.state.name }</p>
//         <p>Score: { this.state.score }</p>
//       </div>
//     )
//   }
// }

const PlayerInfo = ({playerName, playerPoints}) => (
  <div className="player-info">
    <p>Name: { playerName }</p>
    <p>Score: { playerPoints }</p>
  </div>
  )

export default withPlayerData(PlayerInfo)

The results:

App render after adding a Higher-Order Component

And that’s it! We have used a Higher-Order Component to handle our playerData  logic and pass it to our other components. As our applications grow, it’s common to have components that display the same data, but in a different way. That being said, as you can see, Higher-Order Components are useful.

Some HOCs Cons

  • Reusability – can be as much of a con, as it can be a pro. Placing a lot of reusable code into a Higher-Order Component, can involve passing a lot of props, thus leading to collisions.
  • Refs  aren’t passed through.
  • Static methods must be copied over

Where to go from here

If you want to strengthen your understanding beyond this example (which is highly recommended), and don’t have any ideas on what to build next, try making a Higher-Order Component that fetches data from an API, or one that saves/loads a components state to/from local storage. Or how about one that wraps the passed in component in a container with an awesome style ?

Conclusion and Comments

Did you find the examples illustrated in this article too easy? Too complex? Just right? Have something in mind that you would like me to write about? Did you build a fun project using the concepts learned?
Let me know in the comments section below.

In the meantime, Happy Coding! ????

]]>
Full-Stack Web Development Mini-Degree https://gamedevacademy.org/full-stack-web-development-mini-degree/ Sat, 17 Nov 2018 00:30:58 +0000 https://html5hive.org/?p=1961 Read more]]> Go from Zero to Full-Stack Engineer as you build web apps with HTML5, JavaScript, NodeJS, MongoDB, React, GraphQL, Angular, Git, AWS, and Azure. 

This project-oriented curriculum begins by covering the foundations of programming and web development. You’ll learn to create responsive and interactive websites as you get familiar with the basics. We’ll then move on to the server-side and introduce Node.js, Express, Mongo and other frameworks. You’ll be building webapps, REST API’s and scripts.

Following the server-side, we’ll delve further into front-end, this time covering modern frameworks for creating robust applications such as React and Angular. You’ll learn how to integrate these projects with Node.js back-ends and API’s. Finally, you’ll be shown how to use important tools such as Git and Github, and the deployment process to popular platforms such as AWS, Azure and Heroku.

Access this Mini-Degree on Zenva Academy

]]>
The Complete Programming and Full-Stack Bundle – 20 Course Smart Curriculum https://gamedevacademy.org/the-complete-programming-and-full-stack-bundle-20-course-smart-curriculum-html/ Fri, 02 Nov 2018 23:30:00 +0000 https://html5hive.org/?p=1967 Read more]]> ???????? Go from beginner to full-stack developer!

The Complete Programming and Full-Stack Bundle is the world’s most effective way to go from beginner to professional coder. Whether your goal is to advance your career, start your own business or expand your existing skill-set, our 20-course Smart Curriculum has something in store for you.

This bundle is suitable both for absolute beginners and more advanced developers. Projects cover a wide range of different topics including:

  • Crafting interactive websites and web applications with Bootstrap, Angular, React, Node and Express
  • Coding in Python and building smart Machine Learning and AI applications
  • Building games with Unity, Phaser and JavaScript
  • Creating stunning Virtual Reality games and applications
  • Game artwork creation with Blender and Gimp

Access The Complete Programming and Full-Stack Bundle on Zenva Academy

]]>
Creating your First App in React https://gamedevacademy.org/first-react-app-tutorial/ Sun, 13 May 2018 23:07:14 +0000 https://html5hive.org/?p=1945 Read more]]>

You can access the full course here: Build Web Applications with React

The instructions in the video for this particular lesson have been updated in the written portion below.

In this lesson, we’re going to start making a new web application and render our first bit of React.  While this lesson will not be reflective of how practical application of React works, it will allow us to get our feet wet.  You may find it helpful to have both Atom and your chosen web browser open.

Project Setup and Hello World

Within Atom, open up the Terminal and use cd to change into whatever directory you use to store your projects (remember that Terminal defaults to your home directory).  Projects tend to be centralized to a single folder, so we’re going to make a new directory called hello-world.  After it’s created, we will change into that new directory.

mkdir hello-world
cd hello-world

Next, we will create a simple HTML file called index.

Mac:
touch index.html
Alternative for Windows:
echo index > index.html

Let’s open our entire project in Atom now.  By clicking File and then Open, we can find the project folder we created earlier and open up the entire folder.  Once open, you should be able to see the entire folder listed on the left side under the Project tab.

Atom.io code editor welcome screen

Now, to open the files for the project, all we have to do is click them from that side bar.  Knowing this, we will open index.html and populate it with some simple HTML.  For this file, and besides the usual HTML required tags, we will have a simple div with “Hello World!”

<!doctype html>
<html lang="en">
<head>
</head>
<body>
    <div>Hello World!</div>
</body>
</html>

To test the file, locate index.html in its project folder and open it up in your browser.

Hello World rendered via React app

Adding React

The following section’s instructions have been updated, and differs slightly from the video:

We have our file rendering, but obviously we aren’t using React (https://reactjs.org/) at all for this project yet.  In order to use React, we first need to head over to its GitHub page (https://github.com/facebook/react/releases).  For this course, make sure to use the latest release of version 16, as there might be breaking changes otherwise.  The minor version, like .2 or .8, doesn’t matter.  After locating the correct version to use, select the react-dom option from the Artifacts list:

React artifacts with React Dom circled

Next, locate the react-dom.development.js file and right click to select Save Link As.  From there, you can navigate to the hello-world directory and save the file.

react-dom.development.js file right-cliked

After this, head back to the Artifacts list on the GitHub page and select react.  There, you should find a react.development.js file that you can also right click and save to the hello-world directory.

react.development.js file right-clicked

Back in Atom, you should see both files listed in the Project sidebar now.

React hello world project files in Atom.io

Using React on the DOM

Now that we have our files, we can add them to our index.html file.  Under our “Hello World” div, we will add both scripts via script tags.  However, we will also add our own custom Javascript for testing purposes and log a simple message to the console.

<script src="./react.development.js"></script>
<script src="./react-dom.development.js"></script>
<script type="text/javascript">
  console.log('it is working')
</script>

If you refresh and test the page again in your browser, you can right click and then use Inspect to look at the page.  At the bottom, if you hit the Console tab, you should be able to see our printed console message, verifying all is working.

Chrome Console with it is working message via React DevTools

However, this barely uses React at all, so let’s fix that.  Back in Atom, locate the “Hello World” div now.  We will delete the contents of the div while also giving the div an ID of root.

<div id="root"></div>

Under our console.log message, but in the script tag, we’re going to set up a variable that selects the root by its ID.

const mountElement = document.getElementById('root')

(Note: Const is from ES6 and is used for variables that aren’t meant to change).

The next thing we’re going to do is mount a React element onto the DOM.  Using the render function on ReactDOM, we can create an element.  Within this createElement function, we can specify the tag type as the first argument and the tag’s contents, in this case “Hello World”, with the third argument.  After which, we just need to mount it to our mountElement variable, which as you may recall is our root div.

ReactDOM.render(
  React.createElement('h2', null, 'Hello world'),
  mountElement,
)

When we refresh index.html in the browser, we can still see our “Hello world” text.

Hello world rendered in browser via React

If you Inspect the element, you can see in the Elements tab that the div had the h2 tag from create element function added dynamically.

Chrome Inspector showing how React dynamically added element

In the next lesson, we will learn about components.  In the meantime, you can learn a bit more about ReactDOM via the following documentation: https://reactjs.org/docs/react-dom.html

Transcript

In this video we’re going to use Atom’s terminal to start making your brand new app. And we are going to render your first React component. I hope you’re excited.

Okay, so what we have here is our Atom browser, our Atom editor, and a web browser on the right side. In the Atom browser, open up your terminal and if you forgot, that is the plus button up here or it is Control + back tick. And what we’re going to to do is get into your project’s directory. Now some people like to put their projects in their home folder. I put mine in a directory called coding, because this is my coding project. So I’m going to do cd, and cd is short for make the terminal go into this directory. You can think of it as equivalent to double clicking a folder in your computer.

So cd Documents/coding. And now I’m in the coding directory. Once you’re in your projects directory, we’re going to make a new directory. For the most part, web applications tend to be centralized in one directory, so as long as you have one directory that contains all of your source code, then you should be good to go.

This app is going to be simple. It’s gonna be called hello world. So let’s make a directory called that. The command for that is mkdir. It stands for make directory. So make directory hello-world. And let’s cd into that directory. And here we are. We are in the hello-world directory.

And now let’s make an html file. So remember the syntax for making a file is touch index.html. Now let’s go see our project. We can open up our entire project in Atom by clicking on File, Open, and then just navigate to your project. I clicked on hello-world and now I see the project browser on the left side where I have a folder called hello-world and then I had my index.html, which is empty.

Let’s populate with some simple html. Start with the doctype. And then I start with html. Language is English. Direct to close it. The head, I don’t really know what should go in there, so I’m gonna just leave it empty. We’re gonna have a body. And let’s just say div. Hello World, close div.

You might wonder, why are we writing in html when this is a React course? Well, I’m gonna show you how to make, write React code right in an index of html file, even though this isn’t how it’s done in the real-world at all. But just to get your feet wet with React, and not have to commit to the giant boiler plate known as Create React App.

What I’m gonna do now is, I’m gonna show this in Finder. And I’m just gonna open it. So I’m gonna drag it over to my Chrome, because right now my default browser’s set to Firefox, so I drag it to Chrome. Get rid of that guy for a second. And you can see that I have Hello World rendering. Well that’s nice.

What about React? Well to get React, we are going to do this one time download of the library. So go to reactjs.org. And click on get started. Okay, so it’s a little bit actually to the right. Click on this version up here, so 16.2.0. Now it’s important that you do use the same version of React as I am, at least version 16. This minor version, the two, it could be three, four, five. What I’m concerned with is the major version, because every time they increment this number, it has always had breaking changes.

Now I will do my best to keep this course as up to date as possible. But for the time being, 16 is the latest, so go ahead and use 16, because if 17 is out by the time you are viewing this, and you use 17, but follow the 16 tutorial, things might be broken. And I don’t want that to happen to you ’cause it’s really hard to debug when you have different versions. What we’re gonna do is get two libraries, react-dom and react. So you want the development version, ’cause we are in development. So right click on this and click on save link as. Okay and what we’re gonna do is navigate to our folder. Coding, and it’s under hello-world. Save that there. And then do the same thing with react.development.js.

Okay so now you should have two files in your hello-world project. Or three files, index.html, react-dom.development.js, and react.development.js. Okay so what we’re going to do now, let’s get this a little bit smaller so there’s more room. What we’re going to do now is use these scripts. So the syntax for using the script is, script source equals and since they’re right in the same directory, we can navigate to that react-dom.development.js. Close the script tag and let’s do it again with react.development.js. End the script tag. Save it.

Okay and now, let’s actually write some JavaScript. Script, let’s see. Type is text javascript. And just to make sure that this javascript is working, it added it twice, just do a console.log. It’s working. Okay, so no contractions there. Okay, let’s make this window a little bit smaller so I can make this a little bit bigger. Great. And so if I refresh this and I inspect it, I’m gonna take a look at the console, it has an error. So it says react.dom was loaded before react. Make sure you load react, before loading react.dom. Okay, so let’s go ahead and do that. I don’t like big red errors. So hit save. And I refresh. And now they’re saying to download React DevTools. Well I already have that, so let’s ignore that, but we do have our console log that said, it is working.

Okay so the first thing we’re going to do is we are going to make a div, which we already have. Let’s delete the contents of this div and give it an id of root. Now the only reason we are giving this an id is because we need to select it. So let’s make a variable called mount. So const mountElement equals document.getElementById root. And in case you’re not familiar with with ES6, const is another, is a block scoped variable declaration. So in the past, in ES5 and below, you used to declare variables using var. Var is still valid, but var has a lot of different overhead that a lot of people don’t really understand. So what I like to do is I like to use const to signify that I have a constant variable that is not meant to change.

If you have variable that will change, you would use let. And of course, you are perfectly free to use var anywhere you see const or let. And I’ll go forward with using const because it’s good to use ES6 when you can. And what we are going to do is we are going to mount a React element onto the dom. And before we had hello-world, well let’s go ahead and do that. So the syntax with that is ReactDOM.render and we are going to create an element. So React.create.element. Let’s make an h2 and we’re gonna put null here. Don’t worry about what it is right now, but the third argument is the text that we wanna put in, so Hello world. And notice the difference in capitalization, that lowercase w, no exclamation point. Before, I did not have that. So let’s go ahead and save.

Pretty air does it’s work and I actually forgot a argument. We need to put mountElement. Okay, so what is this code doing? It’s creating a React element of the h2 variety and it’s mounting it to this mountElement variable, which is the root, the div with the id of root. Okay, so let’s see it in action. All right so we see it is working. We see this Hello world. We can inspect it. And we say an h2 with Hello world and let’s take a look at our React DevTools. Unfortunately, since we are serving from our file system, we actually can’t use React DevTools.

Notice this little error here that says you might need to use a local http server instead of file://. Well that’s what we’re doing right here. That doesn’t mean that we can’t use React DevTools when we develop, it just means that we would need to have an actual development server. And once we actually get into the nitty gritty of building our app, then we will be able to use that development server so that we can use React DevTools, because that is invaluable for programming in React.

Okay, so what have we learned? Well we made a basic html file. There’s nothing really exciting about that. All we did to make React work is we included the react.development.js. We included the react-dom library and then we just have a basic script tag that just has a console.log. It declares a mountElement where we’re going to mount our entire app. And then ReactDOM goes ahead and renders this React component right onto the mountElement. So if we take a look at the inspector again, we see our h2 right under the div with the id of root.

Interested in continuing? Check out the full Build Web Applications with React course, which is part of our Full-Stack Web Development Mini-Degree.

]]>