DEV Community

loading...
Cover image for What JavaScript do you need to know to write Single-Page-Applications more effectively: A Guide

What JavaScript do you need to know to write Single-Page-Applications more effectively: A Guide

UX Engineering
I am a Full-Stack Developer also working at the cross-section of engineering and design.
・11 min read

If you are interested in knowing what aspects of JavaScript are going to be important for frameworks such as React or Vue, then this article is for you.

I will be covering what aspects of JavaScript I have used when developing using React or Vue.

Summary

  • JavaScript Basics
  • Basic DOM Manipulation
  • Arrow Functions
  • Array Methods
  • Asynchronous JavaScript
  • Making Requests to an API using Fetch
  • ES Modules
  • NPM

Before we jump-in, I would just like to mention that it is not absolutely necessary to know all of these concepts to use React or Vue.

I definitely did not know everything when I first started using React and Vue.

Understanding these concepts and how JavaScript works in the browser is important and will give you a good foundation for your learning of React and Vue.

JavaScript Basics

As with everything, the basics of JavaScript are going to be important.

Variables

In JavaScript you can create variables using the keyword const, var and let.

const is used to declare constants - these are variables whose value will not change over time.

const daysOfTheWeek = 7;
Enter fullscreen mode Exit fullscreen mode

let and var are used in the same way with the keyword being placed before the variable name:

let firstName = "Jane";

var lastName = "Doe";
Enter fullscreen mode Exit fullscreen mode

These are generally used when we have variables whose values are going to change over time.

You may be asking yourself, why there are two keywords with the same function.

There is a small difference.

function varExample ()
{
    var name = "Jane";

    if(name === "Jane")
    {
        var name = "Doe"; //    the same variable as above
        console.log(name) //    will return "Doe"
    }

    console.log(name); //    will also return "Doe"
}

function letExample ()
{
    let name = "Jane";

    if(name === "Jane")
    {
        let name = "Doe"; //    new variable is created
        console.log(name) //    will return "Doe"
    }

    console.log(name); //    will also return "Jane"
}
Enter fullscreen mode Exit fullscreen mode

The variable created using var gets updated, regardless of where in the function it is called.

The variable created using let does not get updated, because the value of that variable is specific to the block it is created in.

Now that we know how to create variables in JavaScript, we can move on to looking at datatypes in JavaScript.

Built-in Datatypes

When writing JavaScript, you will not be declaring the type of variable you are creating.

However, it can be helpful to know which data types exist in the wild west of JavaScript:

  • Undefined
  • Number
  • Boolean
  • String
  • BigInt
  • Symbol

For more information on types in JavaScript you can have a look at the awesome documentation by Mozilla

String Manipulation

Being able to manipulate strings is another task that is often needed when building an application.

Adding Two Strings Together

let firstName = "Jane";
let lastName = "Doe";

//joining them using a '+'
let fullNameOne = firstName + " " + lastName;

console.log(fullNameOne);

//or using template string by using backticks(``)
let fullNameTwo = `${firstName} ${lastName}`;

console.log(fullNameTwo);

//both will result in "Jane Doe"
Enter fullscreen mode Exit fullscreen mode

We can directly use the variables we created to build our final string that will be used as part of our user interface.

Strings also have properties we can access such as the length:

let firstName = "Jane"

let firstNameLength = firstName.length

//will output "4"
console.log(firstNameLength);
Enter fullscreen mode Exit fullscreen mode

We can also convert strings to upper- and lower-case using built-in methods:

let firstName = "Jane";

let upperCaseName = firstName.toUpperCase();
let lowerCaseName = firstName.toLowerCase();

console.log(upperCaseName);//Output: "JANE"
console.log(lowerCaseName);//Output: "jane"
Enter fullscreen mode Exit fullscreen mode

These are again just a small sub-section of what you can do using the built-in JavaScript methods.

DOM Manipulation

JavaScript is definitely a powerful language for the web. It allows us to directly alter what we see in the browser. Using JavaScript we can respond to user input.

It is this reactivity that is an important concept to understand, especially when we progress to using React or Vue.

Selecting Elements from a Webpage

The first step in using JavaScript to manipulate the DOM is to know how to select the elements you want to manipulate.

The older approach you may see is this one:

//this will store all elements that have a class of "title" within our heading variable
let heading = document.getElementByClassName("title");

//this will store the element with the Id "submit" within our button variable
let button = document.getElementById("submit");
Enter fullscreen mode Exit fullscreen mode

A newer approach is to use querySelector():

//this will store the *first* element that has a class of "title" within our heading variable
let heading = document.querySelector(".title");

//this will store the element with the Id "submit" within our button variable
let button = document.querySelector("#submit");

//this will store all of the elements that have a class of "title" within our heading variable as an array
let heading = document.querySelectorAll(".title");
Enter fullscreen mode Exit fullscreen mode

Creating DOM Elements

Another great feature of JavaScript is the ability to create elements that get rendered in the browser.

Helpful when you are retrieving data from an api and you want to display it in a list.

//here we have our heading
const heading = document.querySelector('.heading');

//now let us add our subheading
const subheading = document.createElement('h5');
subheading.textContent = "I am a subheading";

//we can now add this subheading to the heading element
heading.appendChild(subheading);
Enter fullscreen mode Exit fullscreen mode

Handling User Input

This may well be one of the most common tasks when it comes to writing React and Vue apps. Which is why it is also important to understand how it works.

Assume we have a form and we want to get the input the user has entered into the field for the username.

There will be two parts to this form, an input field and a button:

<input type="text" class="username">
<button class="submit-btn" onClick="submitData()">
  Submit
</button>
Enter fullscreen mode Exit fullscreen mode

Using onClick we can define what needs to happen when the button is clicked:

const submitData = () => {
        let username = document.querySelector(".username").value;

  console.log(username);  //will print our the text entered in the input field to the console
}
Enter fullscreen mode Exit fullscreen mode

We can also adjust this to validate the user input every time a new character is added to the input:

<input type="text" class="username" onkeyup="logInput()">
<button class="submit-btn" onClick="submitData()">
  Submit
</button>
Enter fullscreen mode Exit fullscreen mode
const logInput = () => {
    let username = document.querySelector(".username").value;

  console.log(username); 
 //will produce if typed slow enough:
 // "J"
 // "Ja"
 // "Jan"
 // "Jane"
}
Enter fullscreen mode Exit fullscreen mode

There are many different events that can be triggered based on user input.

Dynamically Styling Elements using JavaScript

JavaScript allows us to dynamically update the styling of our UI, allowing us to give feedback to user in response to their input.

Very handy when we are validating the e-mail in a form:

<input type="text" class="user-email" onkeyup="validateInput()">
Enter fullscreen mode Exit fullscreen mode

We are validating the e-mail on every character, giving the user the feedback and letting the know, if their input is valid or not.

This saves them the frustration of submitting data that they then have to correct later on, after the submit fails the validation check.

const validateInput = () => {
    //select the input element
    let emailInputElement = document.querySelector(".user-email");

  //get the value of the input field
  let userEmail = emailInputElement.value;

  //decide if the e-mail is valid or not
  if(!userEmail.includes("@"))
  {
    //here we are adding the red border of the e-mail is valid
    emailInputElement.classList.add("invalid-input");

    //and removing it, if the e-mail becomes invalid again
    emailInputElement.classList.remove("valid-input");
  } else {
        //here we add the green border if it is valid
        emailInputElement.classList.add("valid-input");

      //and remove the red border
      emailInputElement.classList.remove("invalid-input");
  }
}
Enter fullscreen mode Exit fullscreen mode

With these manipulations I definitely would encourage you to try and build a few small projects where you focus on using JavaScript to build-in some reactivity into your app.

Arrow Functions

In a couple of the examples I have shown you, you may already seen this "=>" appear. These are called arrow functions and allow us to simplify the more traditional function declaration:

//traditional JavaScript function
function generateFullName(firstName, lastName){
    return `${firstName} ${lastName}`;
}

//will return "Jane Doe"
console.log(generateFullName("Jane", "Doe"));

//arrow function with name
const generateFullNameArrow = (firstName, lastName) => `${firstName} ${lastName}`

//arrow function returning "Jane Doe"
console.log(generateFullNameArrow("Jane", "Doe"));
Enter fullscreen mode Exit fullscreen mode

Array Methods

These are perhaps one of the most widely used aspects of JavaScript when it comes to dealing with data being retrieved from an API.

In JavaScript arrays can be created using the following syntax:

let nameArray = ["Jane", "John", "Sarah", "Mike"];
Enter fullscreen mode Exit fullscreen mode

Very simple right?

We store the data in a variable, which is why we need a let at the beginning.

Arrays have different methods that allow us to interact and manipulate the data inside.

Going over each item

To go over each item in array we can use the forEach method:

nameArray.forEach(name => console.log(name));

//    Output: "Jane"
//    Output: "John"
//    Output: "Sarah"
//    Output: "Mike"
Enter fullscreen mode Exit fullscreen mode

This does exactly the same as a for-loop:

for(let i = 0; i < nameArray.length; i++)
{
    console.log(nameArray[i]);
}

Enter fullscreen mode Exit fullscreen mode

The forEach method allows us to write less code, but there is not a right or wrong way to go about this.

The console.log(nameArray[i]); is how we can access specific elements within an array.

We need to know what index the element within an array has.

For our nameArray array, we have the following:

//index             0       1       2        3    
let nameArray = ["Jane", "John", "Sarah", "Mike"];

//accessing the name Sarah
console.log(nameArray[2]);
Enter fullscreen mode Exit fullscreen mode

In JavaScript the index starts at 0 and goes up.

Filtering items

JavaScript also has a built-in filter() function that allows us to take the original array and create a new one with items, that fulfill a certain criteria.

//will give us a new array with names that have 4 letters or less
let namesThatHaveFourLetters = nameArray.filter(name => name.length <= 4);

//output: ["Jane", "John", "Mike"]
console.log(namesThatHaveFourLetters);
Enter fullscreen mode Exit fullscreen mode

This will only include names that have 4 characters or less in them.

Applying changes to all items

Another great method that I can recommend using is the map() method.

It allows us to apply changes to each item of an array:

let randomNumbersArray = [1, 2, 3, 4, 5];

let doubledNumbersArray = randomNumbersArray.map(number => number * 2);

console.log(doubledNumbersArray);

//output: [2, 4, 6, 8, 10]
Enter fullscreen mode Exit fullscreen mode

Adding and Removing Items from an array

Another task that does come up is adding and removing items from an array:

//add item to the end of an array
let nameArray.push("Amy");

//add item to the start of an array
let nameArray.unshift("Tom");

//remove item from the end of an array
let nameArray.pop(); //removes "Amy" from array

//remove item from the start of an array
let nameArray.shift(); // removes "Tom" from array
Enter fullscreen mode Exit fullscreen mode

I again recommend that you have a look at the documentation for Mozilla, where there is a more complete list of what is possible with arrays in JavaScript.

Asynchronous JavaScript

This is a key concept when looking using JavaScript-based technologies.

A synchronous app would be one that we are generally familiar with - one line of code is executed after another and there are no two tasks being executed alongside each other.

This can become a problem when you are executing an intensive piece of code and are waiting for that to finish before going on to the next task. If this happens with in the browser, you may well see no response and think the browser has frozen.

You will find that many tasks that relate to fetching some sort of resource from a server now feature asynchronous code to run.

Using setTimeout we can easily show how JavaScript enables us to run code asynchronously:

setTimeout( () => {
    console.log("First console log");
}, 2000);

console.log("Second console log");

//Output:
//"Second console log"
//"First console log"
Enter fullscreen mode Exit fullscreen mode

This is using callbacks to run whatever is inside of the function only after 2 seconds have elapsed.

This means that JavaScript goes onto the next line while the function is waiting to be resolved.

There is a newer and more modern way of writing these types of asynchronous tasks using Promises:

fetch("api/for/some/resource")
//Promises have a characteristic .then()
  .then( response => {
    console.log(response.data);
//it is common to use .catch() to log any errors
}).then( json => {
    console.log(json);
}).catch( error => {
    console.log(error);
});
Enter fullscreen mode Exit fullscreen mode

The code contained within .then() will only be executed, when fetch() returns a result. If the it returns an error instead, the .catch()-block will be invoked.

There is a third level of asynchronous JavaScript that can be achieved using async/await:

//the async keyword comes before the function you want to use await in
const data = async () => {
    //get the resource returned by the api
    const resource = await fetch("api/for/some/resource")
    //convert the returned data to json
    const posts = await resource.json();
    //make it available
    return posts;
}
Enter fullscreen mode Exit fullscreen mode

As you can see this does make your code more readable and cleaner to understand.

Making Requests to an API using Fetch

When working on the frontend of a project, one of the main tasks will be to send and receive data from the backend.

The fetch API provides us with a very convenient way of doing exactly this:

const getUserData = async () => {
    const response = await fetch('api/user/resource', {
        method: 'GET' //'POST', 'PUT', 'PATCH', 'DELETE'
    });

    const data = await response.json();

    return data;
}
Enter fullscreen mode Exit fullscreen mode

If we wanted to post data to the server, we simply use the 'POST' method:

const formData = { firstName: "Jane" };

const postUserData = async () => {
    const response = await fetch('api/user/create', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json; charset=UTF-8'
        },
        body: JSON.stringify(formData),
    });

    const data = await response.json();

    return data;
}
Enter fullscreen mode Exit fullscreen mode

The same thing can be done will all other Http verbs that you can use.

This forms pretty much the backbone of building singe-page-applications using Vue or React.

Mozilla have again done a great job in documenting how to use the Fetch API.

ES Modules

Modules allow us to write logic in one file, export the logic we want and import it in the file we need.

This was possible before we had modules:

const library = require('library-name);
Enter fullscreen mode Exit fullscreen mode

While the module syntax looks like:

import library from 'library-name';
Enter fullscreen mode Exit fullscreen mode

In order for us to be able to import any library or logic, we need to first make it available to be imported. This is done using the export keyword.

//roundNumber.js
export default decimal => Math.round(decimal);
Enter fullscreen mode Exit fullscreen mode

We can now use this in our app.js file:

//app.js
import roundNumber from './roundNumber.js';

let decimal = 3,2;

let roundedDecimal = roundNumber(decimal);
Enter fullscreen mode Exit fullscreen mode

In a Vue or React project you will definitely be importing functionality from different third-party tools and also exporting your own logic to be used within the entire app.

Package Management with NPM

When you first start out a new job as a developer, chances are you will be working on an existing project.

This means that you will need to setup and install all of the dependencies for the project.

Luckily, we have something called npm with which we can easily install all of the dependencies defined within the project's package.json file.

To install all of the packages defined in the file, simply run npm install.

You will see a node_modules-directory created, where, you guessed it, all of your modules/dependencies are installed, ready to be imported.

You can also add packages to a project using npm install <package-name>.

Additionally, we can define which modules are going to be used in production (use npm install <package-name> --save) and which are pure development dependencies (use npm install <package-name> --save-dev).

Testing libraries are usually used during development, but are not needed during production.

Lastly, we can also define commands within our package.json that we can then run using npm:

//package.json
{
    "scripts": {
        "dev": "vue-cli-service serve",
    }
}
Enter fullscreen mode Exit fullscreen mode

We can then reference this using npm by running npm run dev which will in this case start up the development server of our Vue app.

Conclusion

I hope this brief overview gave you an idea of what to know when it comes to starting with React or Vue.

Like I wrote in the beginning, it is not necessary to know all of this, but it does help and speed-up your progress by being familiar with these concepts.

Let me know in the comments if I missed anything that is relevant to learning.

Discussion (10)

Collapse
larsejaas profile image
Lars Ejaas • Edited

This is a very useful article for anyone new to frameworks!

If the module isn't exported as default (this could be in a file with multiple exports), it is possible to import the module(s) like this:

import { module1, module2 } from "./modulefile"
Enter fullscreen mode Exit fullscreen mode
Collapse
ux_engineering profile image
UX Engineering Author

Thank you for your reply! Your point is really helpful

Collapse
andrewrooke profile image
andrewrooke

I am certainly no developer, but I was working on a quick simple proof of concept (POC) last week for an SPA (React, with a JSON file for a data store) to fix an internal problem. The biggest issue I struggled with what my lack of understanding of Hooks and passing state between components.

Collapse
ux_engineering profile image
UX Engineering Author

Awesome! Thank you for your reply. I am currently working on an example app where I am using React and Hooks to manage state. I hope I can have that ready soon.

Collapse
mohithgupta profile image
K.Mohith Gupta

Nice article!! But...For detailed explaination on fetch you can read this article here
Anyone having trouble understanding fetch, can read that article

Collapse
ux_engineering profile image
UX Engineering Author

Hi 👋 awesome for sharing! Thank you!

Collapse
drsimplegraffiti profile image
Abayomi Ogunnusi

Nice post.....

I don't understand the the const variable explanation...or is it a typo?

Collapse
peerreynders profile image
peerreynders

Probably should have been

these are variables whose value will not change over time.

but even that isn't correct.

Quote

The const declaration creates a read-only reference to a value. It does not mean the value it holds is immutable—just that the variable identifier cannot be reassigned. For instance, in the case where the content is an object, this means the object's contents (e.g., its properties) can be altered.

The wrinkle is that

Quote:

All types except objects define immutable values (that is, values which can't be changed). For example (and unlike in C), Strings are immutable. We refer to values of these types as "primitive values".

This gives people the impression that const works differently for primitive values and objects - it's just that the binding is immutable - not the value which why you can still modify the internals of objects (and arrays which are objects).

Collapse
ux_engineering profile image
UX Engineering Author

Thank you for helping me out! Awesome explanation!

Collapse
ux_engineering profile image
UX Engineering Author

Thank you for your reply - I tried to make the explanation a touch easier to understand, but I guess it ended up being more confusing 😅