I decided to create a full Web Developer Course that will cover all the technologies that you need to kickstart your Full Stack Developer Journey. No bullshit, everything practical and relevant will be covered.
We will delve into following topics –
HTML
CSS
JavaScript
Node.js
MongoDB
Check out the first video of this series where we cover the introduction to World Wide Web and the Evolution of the World Wide Web. The code for the video (if any) can be found on GitHub.
⭐ Check out the 10 JavaScript Projects in 2 Hours Video of my JavaScript Series where we build 12+ Projects using JavaScript :
In this article, let us see how we can build an Exercise Planner Application using React.js.
✏ Demo for the Project & Initial Setup
So the first thing you need to do is to create a new project. Make sure to install Node.js onto your system because we will be needing that for our project.
We will be using this tool for creating a new React Project :
Create React App :
Install Node.js :
Create a new React Project
// To create a new React Project
npx create-react-app <project_name>
cd <project_name>
// To run the project
npm start
Install React Router DOM package
npm install react-router-dom
Install JSON-server package globally
We will be using JSON-server for our project.
npm install json-server -g
Create a new file – exercises.json
This is the file that will contain all the exercises that we will be needing in this application. This file will serve as a local JSON store for our application.
store/data.json
{
"exercises": [
{
"title": "Pushups",
"details": "Pushups are beneficial for building upper body strength. They work the triceps, pectoral muscles, and shoulders. When done with proper form, they can also strengthen the lower back and core by engaging (pulling in) the abdominal muscles",
"complete": false,
"id": 119
}
]
}
Inside a new terminal, run the json-server by running the command
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { BrowserRouter } from 'react-router-dom';
ReactDOM.render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>,
document.getElementById('root')
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
App.jsx
import {Switch, Route } from "react-router-dom"
import HomePage from './pages/HomePage';
import './App.css';
import CreateExercise from "./pages/CreateExercise";
import Navbar from "./components/Navbar";
import EditExercise from "./pages/EditExercise";
function App() {
return (
<div className="App">
<Navbar />
<Switch>
<Route path="/home" exact>
<HomePage />
</Route>
<Route path="/create-exercise" exact>
<CreateExercise />
</Route>
<Route path="/exercises/:id/edit">
<EditExercise />
</Route>
</Switch>
</div>
);
}
export default App;
Hey everyone 👋🏻, In this article, let us understand the differences between Arrow Functions and Normal Functions.
Arrow Functions vs Normal Functions
We know that we can define JavaScript functions in many ways:
The first way is by making use of the function keyword.
So as an example, consider this piece of code :
function greet(name) {
return `Hey ${name}`;
}
This comes under normal functions that we declare when we write code. Another syntax that we often see getting used in the code is Function Expression Syntax
So let us transform the above function declaration into a function expression :
The second way is using the arrow function syntax :
So let us transform the above code based on function expression to a code that uses the arrow function syntax
const greet = name => {
return `Hey ${name}`;
}
Now if you see any of the above syntaxes can be used for defining functions, what you choose depends on you but knowing the differences between these syntaxes will make it easier to decide regarding the choice of syntax in different cases.
this keyword
this keyword as we know is a property of an execution context. The main use of it is observed in functions and constructors. Here is a video where you can learn about the rules of the this keyword :
this inside a normal function is dynamic. By dynamic, it means that the value of this depends on how we invoke the function. Let us see the ways we can invoke a normal function. So during a normal invocation, the value of this equals to the global object. There is a small exception to this : If the function runs in strict mode, then the this keyword equals undefined. So let us see an example :
function someFunction() {
console.log(this);
}
someFunction();
The above examples logs the window object to the console.
Next, if we have a method that is sitting within an object, then the this keyword when referenced in the scope of method will point to the object that owns that particular methods which also represents the context in which that method is defined in.
So the above code calls the greet method that is sitting inside the someObject object.
Next we can also make use of the call method to perform an indirect invocation, here the value of this equals to the first argument that the call method receives.
function someFunction() {
console.log(this);
}
const someContext = { a : 'some value' };
someFunction.call(someContext);
For the above example code, the this keyword points to the someContext object.
Next, let us see what this equals to in a constructor function that is created using the normal function syntax :
function User() {
console.log(this);
}
new User();
If we invoke the constructor function using the new keyword, then this equals to the newly created instance.
Arrow Functions
Arrow functions do not have their own this, instead they look up the scope chain to find a this that they can use (or until the lookup hits the global scope) much in the same way as a variable resolves its value. So if you reference a variable in a nested scope, then the lookup will go up the scope chain until it resolves its declaration. This in essence means that arrow function does not define its own execution context. This also means that no matter how or where the arrow functions get executed, the this value inside an arrow function always equals the this value from the outer function. IOW, arrow functions resolve the this in a lexical manner.
this value inside the callback of forEach equals to this of the outer function someMethod
Constructors
Normal Functions We now know that normal functions can be used for creating new objects. So for example, if we want to create a new user, then we can create a constructor function with the name User and that will give us the ability to create new instances of a car when used with the new keyword. So let us see the code for this :
So if you see above, User is a normal function. When invoked with the new keyword, new User('alex', 21, 'developer') – new instances of User gets created.
Arrow Functions
Arrow functions cannot be used as constructor. So if you try to invoke an arrow function using the new keyword, JavaScript will yell at you with an error. So let us see an example for this as well :
So for above code, invoking new User('alex', 21, 'developer') will throw an error, specifically this error :
TypeError: User is not a constructor
– Implicit Return
Normal Function
See the following code :
function someFunction() {
return 'some value';
}
const value = someFunction();
console.log(value);
In the above code, we are just invoking the normal function someFunction and at the point of invocation, we receive a value which we store in value variable that we defined above. Now if we omit the return statement in the above code, or if there is no expression after the return statement, the normal function will do an implicit return here with the value of undefined. So let me demonstrate this with the help of an example :
function someFunction() {
'some value';
}
function someFunction2() {
return;
}
console.log(someFunction());
console.log(someFunction2());
In above code, the first console.log will give us undefined because it misses the return keyword, it actually returns nothing. Coming to the second console.log, it does return but there is no value as such, hence this is also undefined
Arrow Function
In case of an arrow function, you can perform implicit return but the condition for same is that your arrow function should contain only one expression. If so is the case, you can then omit the function’s curly braces, and simply do an implicit return for the expression. So let us see an example for this :
const multiplyBy2 = num => num * 2;
console.log(multiplyBy2(3));
The multiplyBy2 arrow function if you see comprises of just one expression num => num * 2. So here the expression is implicitly returned by the arrow function without the use of return keyword.
Methods
Normal Function
Normal functions as we know is the usual way for defining methods on classes.
Let us see an example :
class User {
constructor(name, age, profession) {
this.name = name;
this.age = age;
this.profession = profession;
}
logUserDetails() {
console.log(this.name);
console.log(this.age);
console.log(this.profession);
}
}
const user = new User('alex', 21, 'developer');
user.logUserDetails();
So the above code does works. But let us assume that we need to supply the logUserDetails method as a callback, say for example to a setTimeout or some other event listener. Now in such cases, we may get a wrong context while trying to access the this value. So consider this code :
setTimeout(user.logUserDetails, 1000);
So after 1 second, the above code will call the logUserDetails method on the user object. Now for the above code this points to the window object.
Let us manually fix the context so by correctly binding this value to point to the user object. So for this , we can make use of the bind method.
setTimeout(user.logUserDetails.bind(user), 1000);
In the above code, user.logUserDetails.bind(user) binds the this value to the user instance. So this ensures that we don’t loose the context and that the this keyword is correctly bound to the instance.
There is another workaround for this as well which is using arrow functions.
Arrow Function
Now with the introduction of class fields, we can use the arrow functions as methods inside classes.
Contrary to the normal functions, the method that we define using arrow functions binds this lexically to the instance of the class.
So let us see an example for same :
class User {
constructor(name, age, profession) {
this.name = name;
this.age = age;
this.profession = profession;
}
logUserDetails = () => {
console.log(this.name);
console.log(this.age);
console.log(this.profession);
}
}
const user = new User('alex', 21, 'developer');
user.logUserDetails();
Now for the above code, if we use user.logUserDetails as a callback without even performing a bind, it will give us the correct values. The value of this inside our logUserDetails will be the class instance itself. So if you try the below code, you will get alex, 21 and developer to the console as output.
setTimeout(user.logUserDetails, 1000);
So this is it for this article. Thanks for reading.
If you enjoy my articles, consider following me on Twitter for more interesting stuff :
Hey everyone 👋🏻, In this article, let us understand When and when not should we use arrow functions.
Arrow Functions
With ES6, JavaScript has evolved a lot because of the customizations that the new standard brings to the language. It has immensely improved our development experienced with the introduction of Next Generation JavaScript features. One of such features that ES6 brings to the table is the Arrow Functions. The purpose of writing this article is to make the reader aware about the scenarios where he/she should not use arrow functions and instead make use of the good old school function syntax or the function expression syntax. We need to be a bit careful as well while using arrow functions because they can affect the readability of our code as well.
When to use Arrow Functions ?
There are some solid reasons why using arrow functions can be a plus.
Securing the scope : The arrow functions remember their context in which they are defined in and they stick to that. So even if we introduce a normal callback function and mix that with a couple of arrow functions, then that can lead to messing up of the scope.
Compact : Easier to read and write. Just a fat arrow, and they can be anonymous as well.
Code Clarity: When every function in your code is an arrow function, then a normal function is the one that we rely on for defining the scope. So we as developers can always look up the next higher order function statement to figure out the this keyword.
When not to use arrow functions ?
1. Defining methods on an object
In JavaScript, as we know a method is a function that we set in a property of the object. So right at the time of invoking the method, the this keyword points to the object that the method belongs to.
Now let us talk about Object Literals here. Let us say we want to define a method inside an object literal. At first, you might be tempted to use an arrow function for a method definition within the object literal. But let us understand with the help of an example, why you should not use an arrow function within the object literals.
user.get_total_invested method as we can see is defined within an arrow function. But if you try the above code, the invocation to user.get_total_invested would throw a TypeError because in the above case this.stocks would resolved to undefined.
Now the thing to note here is that when we are invoking the get_total_invested method on the user object, the context in which it is called in is the window object which we can easily verify by comparing this keyword with the window object in the get_total_invested method as you can see within this method, the this keyword points to the window object. So in essence, this.stocks resolves to window.stocks and this ultimately gives us undefined because we don’t have any stocks property on the window object.
In order to solve this, we can simply switch to the function expression syntax or its shorthand for method definition. For this case, at the invocation point, this keyword would refer to the the thing to the left of the dot at the invocation point. Here is the code with the above modifications :
Now in the above code, get_total_invested is a method that is being called on the user object. So with the regular function syntax, the thing to the left of dot which is the user object here is what this resolves to in the end and therefore the above code would work fine. Here is the output for the above code :
From the output, you can also easily decipher that the this keyword indeed points to the user object and hence this === user returns true as a result.
Let us now move forward and take arrow functions with Object Prototype
Now here also the same thing holds true as discussed above. In the above code, instead of using the arrow function syntax for defining our sayHello method where the this keyword points to window we should instead use the function expression syntax to solve this. So here is the modified code :
So with just this simple change, sayHello regular function is changing its context to user object when called as a method : user.sayHello().
2. Arrow Functions cannot be used as constructors
For constructors, use regular functions otherwise JavaScript will throw an error if it encounters an arrow function getting used as a constructor. This means that JavaScript implicitly prevents from doing that by throwing an exception.
Let us go a bit deeper inside and try to understand a bit more on this :
In simple words, the objects (or the “constructors”) rely on the this keyword to be able to be able to be modified.
The this keyword always references the global object which is the window object.
So if we have something like this :
const User = (name, age, profession) => {
this.name = name;
this.age = age;
this.profession = profession;
}
const user = new User("Alex", 21, "developer");
Executing new User("Alex", 21, "developer"), where User is an arrow function, JavaScript throws a TypeError that User cannot be used as a constructor.
But, instead if you do something like this :
const User = function(name, age, profession) {
this.name = name;
this.age = age;
this.profession = profession;
}
const user = new User('Alex',21,'developer');
console.log(user.name);
Now here, the new keyword does some magic under the hood and makes the this keyword that is inside the User to initially first refer to the empty object instead of referencing to the global object like it earlier did. Right after this, new properties like name,age and gender get created inside this empty object pointed to by the this keyword and the values will be Alex,21 and developer respectively. Finally, the object pointed to by the this keyword gets returned.
Now a thing to note here is that arrow functions do not allow their this object to be modified. Their this object is always the one from the scope where they were statically created. This is called Static Lexical Scope. This is precisely the reason that why we cannot do operations like bind, apply, or call with arrow functions. Simply, their this is locked to the value of the this of the scope where they were created.
3. Arrow Functions as callback functions
As we know in client side JavaScript, attaching event listeners to the DOM elements is a very common task. An event triggers the handler function with this as the target element.
Now as discussed just a while back, this points to the window object in an arrow function that is defined in the global context. So whenever a click event occurs, browser tries to execute the handler function with the button as context, but arrow functions still stays bound to its pre-defined context. In above code, this.innerHTML is same as window.innerHTML which does nothing infact.
In order to solve this, we need to make use of the function expression syntax which will allow us to change this depending on the target element.
Now for the above code, this keyword will infact point to the button. Therefore, this.innerHTML will correctly modify the button text and reflect the same in the UI.
So this is it for this article. Thanks for reading.