React Training

Day 1

Bartosz Szczeciński
GFT Poland

Do you know JS?

created by Brendan Eich of Netscape in only 10 days

JavaScript is the most popular implementation of ECMA Script

Other implementations include Action Script used in Flash

ES3 and ES5 are the current "standard" as they are supported by all major browsers

Inconsitency

different browsers implemented JS differently

some didn't implement things at all, implement them 
​differently than other browsers 

developers had to do two or three time as much work
to support things like event listeners

First Frameworks

Prototype, Mootools, jQuery were some of the most popular frameworks that emerged in and after 2006 - most of them are still in use today

First Frameworks

they allowed for a unified access to DOM, events and other JS parts of JS - while still not compatible with each other they allowed for the same code to run on different browsers

// jQuery
$('div.foo').on('click', function() { 
    alert('Hello!'); 
});

// mootools
$$('div.foo').addEvent('click', function() {
    alert('Hello!');
});

// prototype
$('div.foo').observe('click', function() {
    alert('Hello!');
});

First "mature" frameworks

as more complex applications were starting to emerge in the browser ecosystem people wanted a tool to ease their work and make it more like writing normal apps

Backbone, Javascript MVC and Knockout JS were some of the first frameworks aimed for developing big apps

Complete package

based on ideas of the previous frameworks, Angular (sometimes called Angular JS, ng) was introduced as a "complete package" solution for developing interactive single-page applications.

 

With the expansion of mobile market, Angular was often implemented with Apache Cordova to provide a "native like" experience for the use and required only knowledge of HTML an JS with some of the API to access real hardware

Thinking outside of the browser

in 2009 an  project was started as ServerJS that aimed to provide an environent to JS outside of the browser, it was later renamed CommonJS.

 

One of the features was introduction of modules, which in 2010 was implemented in the npm project. This allowed for the creation of specialized modules that could connect with each other to form bigger software.

Do one thing - do it right

Going with the idea of doing one thing and doing it right Facebook developed a library which helped them solve issues of updating multiple pieces of UI from a single data store - ReactJS in 2011

 

It wasn't untill 2013 that the project went Open Source

Hello, React!

React in itself doesn't offer many features - it focuses mostly on high-performance UI updates. The language was inspired by XHP - a PHP (Hack) extension that allowed usage of XML directly in PHP code of Facebook projects.

 

If a developer requires state management, integration with REST enpoints, form validations etc. he is required to either roll out his own or to integrate third party solutions.

Going further

React idea was later expanded to React Native which allows developers to write code similar to normal ReactJS which is subsequently compiled to either Android or iOS binaries and ran as a full-fledged apps, not as apps embeded within a browser window.

 

This allows developing faster, almost native level applications.

React native is not yet production ready - it has a small library of components and has many open issues.

State of JS - 2016 and beyond

rapid expansion to browsers and beyond

new features introduced in big bulks and small doses - ES6, ES Next

a new tool for every project, a new tool every month

bigger expectations, bigger apps, more security risks

State of JS - developers

constant changes in technology stack 

"JS Fatigue"

breaking changes in app

NodeJS

Up until recently JavaScript was mostly seen as an browser-ran language. In the past years many projects aimed at providing an runtime environment that allowed to build backend and other applications in JS, of which Node.js is the most popular.

 

Node provides a tool which can either run .js files or provide and interactive REPL environment which allows the user to write code and see the results in the CLI window. By default node provides a package manager - npm.

NodeJS

Node is NOT a framework, although it's modular structure and the fact that parts of it are written in JS allow developers to use its components as parts of other frameworks.

Node is NOT an JS engine - by default it uses Google's V8
 engine that is part of Chromium project but there are also forks using Chakra Core engine from Internet Explorer.

NodeJS - Compatibility

It's worth noting that even though Node ES6 compatibility is higher than that of Chrome, it's still not 100%

NPM 

npm is both the name of the client and the repository containing various open source components and providing dependency resolving, updating and more.

 

The most important part of every npm project is the package.json file. You should always create a package.json file for your project. To do so simply call `npm init .` in the root directory.

 

You can also run `npm init . --yes` to create a file with all defaults set.

NPM - usage

# install all packages for current environment found in package.json, 
# along with their dependencies 

$ npm install

# install a package in its current version and 
# save it as a dependency, dev dependency or install it globally

$ npm install package-name` (--save, --save-dev, --global)
# update all packages keeping the package versions compatible to those in package.json

$ npm update
# start the default script provided with the project

$ npm start

# start the default tests

$ npm test

# run an arbitrary script provided by the developer

$ npm run script-name

NPM - package.json

{
  "name": "my_package",
  "version": "1.0.0",
  "dependencies": {
    "my_dep": "^1.0.0"
  },
  "devDependencies" : {
    "my_test_framework": "^3.1.0"
  }
}

Every NodeJS project / npm package should contain an package.json file, consisting of at least its name and version.

Make sure to not create a project with an already taken name, or name of a package you will use (eg. "react") because it will enter a dependency loop.

NPM - symver

~version # "Approximately equivalent to version"
^version # "Compatible with version" 
version # Must match version exactly
>version # Must be greater than version
>=version # etc
1.2.x # 1.2.0, 1.2.1, etc., but not 1.3.0
http://sometarballurl # URL of the .tgz file
* # any version
latest # Obtains latest release

Every package must have its version provided in symver compatible format. package.json can specify which version will your project use:

NPM - shrinkwrap

$ npm shrinkwrap

# package.json

{
  "name": "A",
  "version": "1.1.0",
  "dependencies": {
    "B": {
      "version": "1.0.1",
      "from": "B@^1.0.0",
      "resolved": "https://registry.npmjs.org/B/-/B-1.0.1.tgz",
      "dependencies": {
        "C": {
          "version": "1.0.1",
          "from": "org/C#v1.0.1",
          "resolved": "git://github.com/org/C.git#5c380ae319fc4efe9e7f2d9c78b0faa588fd99b4"
        }
      }
    }
  }
}

Some times we need to use a specific version of a package and even though we declare it so in the package.json, a dependency might update its package.json and get a new file.

To stop this we can use shrinkwrap:

JS of tomorrow - TODAY!

ES6 or ECMSScript 2015 is the most up-to-date standard implemented by JavaScript in the most popular browsers.


It introduces a lot of new and helpful concepts and if not required it is highly recommended to learn and use it in the upcoming projects.


Please note that some of the ES6 features might not be supported by various browsers - to get around that we will introduce the concept of transpiling later on.

Modules

# test.js

function test() {
    // code
}

var PI = 3.14;

exports = {
    test: test,
    PI: PI
}

# test2.js

function test2() {
    // code
}

modules.exports = test2;

# app.js

var myLib = require('./test.js');

myLib.test();
myLub.PI;

var otherLib = require('./test2.js');
otherLib();
# test.js

export var PI = 3.14;

function test() {
    // code
}

export test;

export default test2() {
    // code
}

# app.js

import test2 from "./test.js";
import { PI, test } from "./test.js";
import * as myLib from "./test.js";

test2();
console.log(PI);
myLib.test();

Scoping

var a;
a = 1;
let b = 2;
const c = 3;
const c = 4; // SyntaxError - can't redefine the const

console.log(a); // 1

(function() {
  console.log(a); // 1
  console.log(b); // 2;
})();

if(true) {
  var d = 5;
  let e = 6;
}

console.log(d); // 5;
console.log(e); // ReferenceError - e is not defined

Arrow functions

function Counter() {
  this.value = 10;

  setInterval(function count() {
    this.value++;
    console.log('Value is ' + this.value);
  }, 1000);
}

var c = new Counter();
function Counter() {
  this.value = 10;

  setInterval(() => {
    this.value++;
    console.log('Value is ' + this.value);
  }, 1000);
}

var c = new Counter();

Context matching, destructuring

function matchObject({x, y}) {
  return x * y;
}

matchObject({x: 5, z: 8, y: 2}); // 10
function getMyObject() {         
  return {                       
    x: 1,                        
    y: 3,                        
    z: 18                        
  }                              
};                               
                                 
let { x, z, y } = getMyObject(); 
                                 
console.log(x, y, z); // 1, 3, 18

let [a, b, c = 5] = [1, 2];

console.log(b); // 2
console.log(c); // 5

Destructuring

Importing a module is NOT using the destructuring syntax!

Property value shorthand

let PI: 3.15;

function myMathEquation() {
    // code
}

export {
    PI: PI,
    myMathEquation: myMathEquation
};
let PI: 3.15;

function myMathEquation() {
    // code
}

export {
    PI,
    myMathEquation
};

Template literal

console.log("this is" + 
"an example" + 
"of multi-line string");

let a = 1;
console.log("values of a is " + a);
console.log(`this is also
an example of multi-line
string`);

let a = 2;
console.log(`a = ${a}`);

Tagged templates

function test(str) {                        
  return str[0].toUpperCase();              
}                                           
                                            
let upperCase = test`this is an example string`;                         
                                            
console.log(upperCase); // THIS IS AN EXAMPLE STRING          
                                            
function hasVariables(str, ...variables) {  
  console.log(str); // [ 'a = ', ', b = ', '' ]                       
  console.log(variables); // [1, 2]               
}                                           
                                            
let a = 1, b = 2;                           
hasVariables`a = ${a}, b = ${b}`;           
console.log("A panda looks something like this: 🐼");

Classes

class Person {                                                               
                                                                             
   greet() {                                                                 
    return this.greetingForm + ", " + this.personName;                       
   }                                                                         
}                                                                            
                                                                             
class PersonFromGermany extends Person {                                     
  constructor(name) {                                                        
    super(); /* need to call super() if you are extending a class and overriding the constructor */       
    this.personName = name;                                                  
    this.greetingForm = "Guten tag";                                         
  }                                                                          
                                                                             
}                                                                            
                                                                             
const me = new PersonFromGermany("Bartosz");                                 
console.log(me.greet());  /* Guten tag, Bartosz */                                                   
class Test {   
                      
  set a(value) { this._a = value; }                     
  get a() { return this._a; }                     
}                       
                        
const obj = new Test(); 
obj.a = 5;              
console.log(obj.a);     

Promises

new Promise(function( resolved, rejected ) {
    // asynchronous logic
});

A promise can be in one of the 3 states:

 

pending: initial state, not fulfilled or rejected.
fulfilled: meaning that the operation completed successfully.
rejected: meaning that the operation failed.

The promise object has 2 public methods:

 

then(onResolve, onReject) - will be called when the promise is fulfilled, it can return another promise to chain them

catch(onReject) - it is an alias to then(null, onReject)

Promises

const p = new Promise(function(res, rej) {
  setTimeout(res, 1000);
}).then(() => {
  console.log("A second passed!"); /* will be called after 1 second */
});
new Promise(function(res, rej) {
  setTimeout(rej, 1000);
}).then(() => {
  console.log("A second passed, again!"); 
}).catch(() => {
  console.log("It looks like the time stopped passing ...."); /* will be called after 1 second */
});
function second() {
  return new Promise(function(res, rej) {
    setTimeout(res, 1000);
  });
};

second().then(() => {
  console.log("A second passed ..."); /* called after 1 second */
  return second();
}).then(() => {
  console.log("And another one!"); /* called after 2 seconds */
  return second();
}).then(second) /* called after 3 seconds - just return a new promise */
.then(() => console.log("Looks like we've skipped a second there ...")); /* called after 4 seconds */

High Order Functions

High order functions are functions that take functions as parameters and return new or changed functions.

function log(f) {
  return function(arg) {
    var val = f(arg);
    console.log("Invoked with '" + arg + "' - got '" + val + "'");
    return val;
  }
}

function toUpper(string) {
  return string.toUpperCase();
}

log(toUpper)("small case text"); /* Invoked with 'small case text' - got 'SMALL CASE TEXT' */
const loggedToUpper = log(toUpper); /* can now just do loggedToUpper("text"); */

Transpiling

Because there is no 100% support of ES6 in many of the browsers we need to use so called transpilers or source-to-source compilers which take source code written in one language and output the same application in another.

 

In our case we will be using babel to transpile ES6 to ES5.

 

We might also use solutions known as Polyfill to add functionality not supported in target browsers
(for example IE11 doesn't support Promises).

Transpiling

React Training 2016

By btmpl

React Training 2016

  • 389