-- cover # ES6
BabelReact -- cover # ES2015
BabelReact -- who **David Barral** david@trabesoluciones.com @davidbarral **Román Coedo** roman@trabesoluciones.com @rcoedo **Asís García** asis@trabsoluciones.com @asischao -- slidepack ## Esta charla está hecha con # SlidePack ## _"Simple slides generator & viewer"_ [trabe.github.io/slide-pack](http://trabe.github.io/slide-pack) -- disclaimer ## Pregunta # ¿Cuánto sabéis de JavaScript? funciones, prototipos, hoisting, closures, bindings, etc, etc. -- # OBJETIVOS ## Introducir las features de ES2015 ## Ver cómo usarlas hoy ## Introducir React -- # ECMASCRIPT ## ES5, ES2015, ES2016... ## Una spec por año ## stage-0, 1, 2, 3 y 4 -- # ES2015 ## el artista antes conocido como ES6 http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf -- # `let` y `const` ## Mutable vs inmutable ```javascript // ES6 let counter = 0; counter++ // This is fine const PI = 3.14; PI++ // This is not fine ``` -- # `let` y `const` ## Mutable vs inmutable ```javascript // ES6 const john = { age: 25 }; jhon.age++ // No problem! Ups! jhon = { age: 99 }; // This is not fine; ``` -- # `let` y `const` ## var: function scope y hoisting ``` // ES5 if (true) { var a = 1; } console.log(a) // 1 ``` -- # `let` y `const` ## var: function scope y hoisting ``` // ES5 var a; if (true) { a = 1; } console.log(a) // 1 ``` -- # `let` y `const` ## Block scope ```javascript // ES6 if (true) { let a = 1; } console.log(a) // undefined ``` -- # Arrow functions ## syntactic sugar ```javascript //ES5 var square = function(n) { return n * n; } // ES6 const square = function(n) { return n * n; } const square = (n) => { return n * n; } const square = (n) => n * n; const square = n => n * n; ``` -- # Arrow functions ## lexical scoping ```javascript // ES5 not binded var john = { name: "John", age: 25, greeter: function() { return function() { return "Hello I am " + this.name; } } } var greet = john.greeter(); greet(); // "Hello I am " ``` -- # Arrow functions ## lexical scoping ```javascript // ES5 invocation binding var john = { name: "John", age: 25, greeter: function() { return function() { return "Hello I am " + this.name; } } } var greet = john.greeter(); greet.call(john); // "Hello I am John" greet.call({ name: "Mary" }); // "Hello I am Mary" ``` -- # Arrow functions ## lexical scoping ```javascript // ES5 closure var john = { name: "John", age: 25, greeter: function() { var that = this; return function() { return "Hello I am " + that.name } } } var greet = john.greeter(); greet(); // "Hello I am John" greet.call({ name: "Mary" }); // "Hello I am John" ``` -- # Arrow functions ## lexical scoping ```javascript // ES5 explicit bind var john = { name: "John", age: 25, greeter: function() { return function() { return "Hello I am " + this.name; }.bind(this); } } var greet = john.greeter(); greet(); // "Hello I am John" greet.call({ name: "Mary" }); // "Hello I am John" ``` -- # Arrow functions ## lexical scoping ```javascript // ES6 const john = { name: "John", age: 25, greeter: function() { return () => "Hello I am " + this.name; } } var greet = john.greeter(); greet(); // "Hello I am John" greet.call({ name: "Mary" }); // "Hello I am John" ``` -- # String templates ```javascript // ES5 "Hello I am " + this.name // ES6 `Hello I am ${this.name}` ``` -- # Array destructuring ```javascript // ES5 var arr = [1, 2, 3, 4]; var a = arr[0]; var b = arr[1]; var c = arr[2]; var d = arr[3]; // ES6 const [a, b, c, d] = [1, 2, 3, 4]; ``` -- # Array splatting ```javascript // ES6 splatting function reverse(array) { const [head, ...tail] = array; if (tail.length === 0) { return [head]; } else { return [...reverse(tail), head]; } } ``` -- # Object destructuring ```javascript var john = { name: { first: "John", last: "Doe" }, age: 25 } // ES5 var first = john.name.first; var last = john.name.last; var age = john.age; // ES6 const { name: {first, last}, age } = john; ``` -- # Parámetros opcionales ```javascript // ES5 function sum() { var numbers = Array.prototype.slice.apply(arguments); return numbers.reduce(function(a,n) { return a + n; }); } // ES6 function sum(...numbers) { return numbers.reduce((a, n) => a + n); } ``` -- # Parámetros nombrados ```javascript var cylinder = { radius: 0.5, height: 3 }; // ES5 function volume(radius, height) { return 3.14 * radius * radius * height; } volume(cylinder.height, cylinder.radius); // Ups! // ES6 function volume({ radius, height }) { return 3.14 * radius * radius * height; } volume(cylinder); ``` -- # Valores por defecto ```javascript // ES5 function join(words, separator) { separator = separator || ","; return words.join(separator); } // ES6 function join(words, separator = ",") { return words.join(separator); } ``` -- # Clases ```javascript // ES5 function Human(name, age) { this.name = name; this.age = age; } Human.prototype.becomeOlder = function() { this.age += 1; } var john = new Human("John", 25); ``` -- # Clases ```javascript // ES6 class Human { constructor(name, age) { this.name = name; this.age = age; } becomeOlder() { this.age += 1; } } const john = new Human("John", 25); ``` -- # Más syntactic sugar ```javascript // ES6 class Human = { // .. becomeOlder() { ... } // same as: becomeOlder: function() { ... } } ``` -- # Clases ```javascript class Animal { constructor(name, legs) { this.name = name; this.legs = legs; } } class Dog extends Animal { constructor(name) { super(name, 4); } } class Dolphin extends Animal { constructor(name) { super(name, 0); } } ``` -- # Promesas ```javascript // ES6 fetch("/stock_values.json").then( response => response.json() ).then( values => values.filter(v => v > 100) ).then( highValues => console.log(highValues) ).error( () => console.err("Something went wrong") ); ``` -- # Promesas ```javascript // ES6 const loadImage = (src) => { return new Promise((resolve, reject) => { const img = new Image(); img.src = src; img.onload = () => resolve(img); }); } loadImage("awesome_flying_melon.png").then( image => document.getElementById("#wrapper") .appendChild(image) ); ``` -- # Módulos ```javascript // my-math.js export const PI=3.14; export function sqrt(x) { ... }; export default const math = { PI: PI, sqrt: sqrt }; ``` -- # Más syntactic sugar ```javascript // my-math.js export const PI=3.14; export function sqrt(x) { ... }; export default const math = { PI, sqrt }; ``` -- # Módulos ```javascript import {PI} from "my-math"; console.log(PI); // 3.14 import math from "my-math"; console.log(math.sqrt(4)); // 2 import {srqrt as root2} from "my-math"; console.log(root2(4)); // 2 import * as myAwesomeMath from "my-math"; console.log(myAwesomeMath.sqrt(4); // 2 console.log(myAwesomeMath.PI); // 3.14 ``` -- # Más cosas * Clases: extends/super y get/set * Símbolos * Generadores y async/await * (Weak)Maps, (Weak)Sets https://github.com/DrkSephy/es6-cheatsheet https://babeljs.io/docs/learn-es2015/ -- # Soporte en navegadores ## _evergreen browsers FTW_ ## _mobile browsers FTL_ https://kangax.github.io/compat-table/es6/ -- ![](./assets/babel.png) https://babeljs.io -- # Babel ## Un compilador de JS a JS ```javascript // ES6 goes in... const hi = name => console.log(`Hello, ${name}`) // ...ES5 comes out "use strict"; var hi = function hi(name) { return console.log("Hello, " + name); }; ``` -- # Babel playground https://babeljs.io/repl/ -- # Babel ```shell $ npm install babel babel-cli babel-preset-es2015 $ babel input.js -o output.js ``` ```javascript // .babelrc { presets: ["es2015"] } ``` -- # Babel ```shell $ babel-node > (x => 2*x)(4) 8 > ``` -- # Babel polyfill ## Soporte provisional para navegador ```shell $ npm install babel-polyfill ``` ```javascript // In your code import "babel-polyfill"; ``` -- ![](./assets/webpack.png) https://webpack.github.io/ -- # Webpack ```shell $ webpack --config webpack.config.dev.js --watch $ webpack --config webpack.config.prod.js ``` -- ```javascript // webpack.config.dev.js module.exports = { entry: "./main.js", output: { path: __dirname + "dist/"), filename: "bundle.js" }, module: { preLoaders: [ { test: /\.jsx?$/, exclude: /node_modules/, loader: "eslint" } ], loaders: [ { test: /\.jsx?$/, exclude: /node_modules/, loader: "babel", query: { presets: ["es2015", "stage-0", "react"] } } ] }, resolve: { extensions: ["", ".js", ".jsx"] } } ``` -- ![](./assets/eslint.png) http://eslint.org/ -- ``` { "parser": "babel-eslint", "plugins": [ "react" ], "env": { "browser": true, "es6": true }, "settings": { "ecmascript": 6, "jsx": true }, "rules": { "brace-style": [2, "1tbs", { "allowSingleLine": true }], "camelcase": [2, {"properties": "always"}], "react/jsx-no-undef": 2, // ... }, "ecmaFeatures": { "modules": true, "arrowFunctions": true, "jsx": true // ... } } ``` -- # El futuro: ES2016 ``` // ES2016 stage-2 const { name, age, ...rest } = john; console.log(name); // John console.log(age); // 25 console.log(rest); // { id: "12345", favColor: "red" } const mary = { ...john, name: "Mary" }; ``` -- ![](./assets/react.png) https://facebook.github.io/react/ -- # React ## Filosofía * Librería de UI * UI = f(estado) * Virtual DOM * Uniderectional data flow -- # Componentes ```javascript import React from "react"; import {render} from "react-dom"; const HelloWorld = () =>
Hello world!
; render(
, document.getElementById("app") ); ``` -- # What the <Fuck/> !? -- # JSX (syntactic sugar) ```javascript import React from "react"; import {render} from "react-dom"; const HelloWorld = () => React.DOM.p(null, "Hello world!"); render( React.createElement(HelloWorld), document.getElementById("app") ); ``` -- image # Virtual DOM ![](./assets/vdom.png) -- # Props ```javascript import React from "react"; import {render} from "react-dom"; const HelloWorld = (props) =>
Hello {props.name}!
; render(
, document.getElementById("app") ); ``` -- # Funciones vs clases ```javascript import React from "react"; import {render} from "react-dom"; class HelloWorld extends React.Component { render() { return
Hello {this.props.name}!
; } } render(
, document.getElementById("app") ); ``` -- #
¡Estado!
```javascript class HelloWorld extends React.Component { constructor(props) { super(props); this.state = { casual: props.casual }; this.toggleStyle = this.toggleStyle.bind(this); } toggleStyle() { this.setState({ casual: !this.state.casual }); } render() { const greeting = this.state.casual ? "Wasap" : "Hello"; return
{greeting} {this.props.name}!
; } } render(
, document.getElementById("app") ); ``` -- # Children ```javascript const Emphasis = ({children}) => { return (
WOOOOOOOOWWWWW!!! {children} WWAAAAAAAWWWAAAAAAAAAA!!!
); } render(
, document.getElementById("app") ); ``` -- # Otros temas * Ciclo de vida * Contexto * JSX quirks * propTypes -- ![](./assets/react_native.png) https://facebook.github.io/react-native/ -- # React native ```javascript import React from "react-native"; const { DrawerLayoutAndroid, ProgressBarAndroid, Text } = React; class App extends React.Component { render() { return (
React Native
}>
); } } ``` -- # En el próximo capítulo ## La M del MVC * Unidirectional data flow * Flux * Redux ## Miércoles 6 de abril -- image # ¿Preguntas? ![](./assets/questions.jpg) -- # ¡Hasta el próximo capítulo! ![](./assets/gunter.gif)