Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Developing in MapStore - Part 1a - Front End Technologies

Developing in MapStore - Part 1a - Front End Technologies

First module of our Developers Training for MapStore: introduction to ES6 / React / Redux

Simone Giannecchini

February 11, 2021
Tweet

More Decks by Simone Giannecchini

Other Decks in Technology

Transcript

  1. JAVASCRIPT EVOLVES WITH IT • Need for a more expressive

    language ◦ do more with less (lines of code) ◦ simpler structures (for async) • Web Applications more complex than ever ◦ Mobile/Desktop ◦ High Reliability ◦ Soft Failing ◦ Caching ◦ Offline ◦ Notification ◦ ... • → Need for libraries that allow to manage complexity
  2. MapStore • Uses modern technologies and programming paradigms to: ◦

    Simplify programming / (unit) testing /debugging ◦ Faster development / Maintainability ◦ Less error prone / reproducible errors, when present • ECMAScript (Official name of JavaScript) • React • Redux • RxJS Let’s see them in the next slides !
  3. ECMAScript Standard Name for JavaScript (ECMA-262) • ECMAScript 5 (December

    2009) - Most used until recent years • ES2015 a.k.a. ES6 (class, arrow functions, spread, Promise …) • ES2016 a.k.a. ES7 (...) • ES2017 a.k.a. ES8 (...) • ES2018 a.k.a. ES9 (...) • ES2019 a.k.a. ES10 (...) • ES2020 a.k.a. ES11 (Optional chaining, Nullish Coalescing, dynamic import)
  4. ES6 - Class A class is a type of function,

    but instead of using the keyword function to initiate it, we use the keyword class, and the properties are assigned inside a constructor() method. class Polygon { constructor (height, width) { this .h = height; this .w = width; } test() { console.log ("The height of the polygon: " , this.h) console.log ("The width of the polygon: " , this.w) } } //creating an instance var polygon = new Polygon(10, 20); polygon.test();
  5. ES6 - Arrow Function Concise syntax for writing function expressions.

    Arrow functions are anonymous and change the way this binds in functions. // function without arguments () => { /* some code */ } // one argument don’t need parenthesis (), implicit return argument => value // return an object - use ({}) (not function body) argument => ({ object: “to return” })(arg1, arg2) => { return arg1 + arg2; } // this is the this at the definition scope () => this.fun()
  6. ES6 Variable declaration Other than classical var, you can declare

    variables using const and let // cannot be re-assigned new content, static check const a = “MY_CONST”; // block scoped var (var was function scope) let a = “myvar”
  7. ES11 Optional Chaining Shortener for null or undefined (nullish) checks,

    returning `undefined` if something is nullish in the chain. // if `obj.attr1` doesn’t have `attr2`, you have an error const a = obj.attr1.attr2.attr3; // to prevent issues you usually needed to do do something like this... const a = obj.attr1 && attr1.attr2 && attr1.attr2.attr3; // with optional chaining const a = obj?.attr1?.attr2?.attr3; // it can be used for: obj?.prop // object props obj?.["expr"] // object props accessed with [] operator arr?.[1] // arrays func?.(args) // functions, prevents errors if function is undefined on function call. const obj = { attr1: { attr2: { attr3: "hello" } } }
  8. ES11 - Nullish cohelish Returns default values in case of

    nullish. Is more secure than the usual && || checks, because it works also in case of values 0 or empty strings (that are false) const a = null; const foo = a ?? 'default string'; console.log(foo); // expected output: "default string" const baz = 0 ?? 42; console.log(baz); // expected output: 0
  9. ES6 spread operator Spread operator allows an iterable to expand

    in places where 0+ arguments are expected. Is mostly used for array or objects. var array = [3, 4] // Spread operator for arrays var newArray = [1, 2, ...array] // result ->[1,2,3,4] (new Array) const obj = { a: “a”, b: “b” }; const d =”d”; // Spread operator for objects const newObj = { ...obj, c: “c”, d }; // newObj = { a: “a”, b: “b”,c: “c”, d: “d”}
  10. ES6 Destructuring Destructuring assignment allows us to “unpack” arrays or

    objects into a bunch of variables. Is mostly used for array or objects. var array = [1, 2, 3, 4] // array destructuring var [a, ,b] = array; // same of var a = array[0]; var b = array[2] // a =1, b=3 // ------ // object destructuring var object = { A: “A”, B: “B”, C: ”C” }; var { A, B } = object; // same of var A = object.A; var B = object.B // A= “A” , B= ”B”
  11. ES6 Default Value - Rest operators Default Value Rest operators

    var obj = { a: “a”, b: “b”, c: “c” }; var array = [1, 2, 3, 4]; // rest operator for destructuring objects or arrays var { a: s1, ...other } = obj; // s1=”a”, other= {b:”b”, c:”c”}, var [n1, n2, ...rest] = array; // n1=1, n2=2, rest = [3,4] // rest operator for functions fun = function (a, ...b) { return b; } // rest parameter (array of last parameters) fun(1, 2, 3, 4); // return [2,3,4] (x = 42) => x // default values for function parameter
  12. ES6 Array map/filter/reduce map create a new array, same length,

    with result of function filter creates a new array with only the elements that reduce( (accumulator, current) => nextAccumulatorValue, initialAccumulatorValue) ◦ (acc: 0 + next: 1) 1st Iteration ◦ (acc: 1 + next: 2) 2nd Iteration ◦ (acc: 3 + next: 3) 3rd Iteration Composition: [1, 2, 3].filter(a => a > 1) // [2,3] [1, 2, 3].reduce((a, b) => a + b, 0) // 6 [1, 2, 3].map(a => a + 1).filter(a => a > 1).reduce((a, b) => a + b, 0) // result ?? [1, 2, 3].map(a => a + 1) // [2,3,4]
  13. ES6 Array map/filter/reduce Result: [1, 2, 3] .map(a => a

    + 1) // [2,3,4] .filter(a => a > 1) // [2,3,4] .reduce((a, b) => a + b, 0) // acc: 0 + next: 2 // acc: 2 + next: 3 // acc: 3 + next: 4 // result = 9
  14. ES6 - Promise Create a Promise (native) Axios (library used

    in MapStore) Chaining Promise: Pattern to represent and handle incomplete operations. var promise = new Promise(function (resolve, reject) { resolve(42); // here you can imagine ajax requests, setTimeout ... }); promise.then((function (result) { console.log(result); // 42 })); var ajaxCall = axios.get(“URL”); // axios.get returns a new Promise ajaxCall.then((function (result) { console.log(result); // ajax response object })); axios.get(“URL_1”) .then((function (result_1) { return axios.get(“URL_2”); // if return a Promise, you can chain then calls }).then((function (result_2) { console.log(result_2); }).catch(function (error) { … }); // handle errors from the chain
  15. ES6 - Promise Pipeline of callbacks • Limitations ◦ no

    cancellation ◦ single value ◦ complex flows of async actions still nested
  16. A javascript library for building user interfaces • Declarative •

    Component based • JSX • functional in core • Optional state • Virtual Dom • Easy Optimization React // (Stateless Functional) Component const Welcome = (props) => { return <h1>Hello, {props.name}</h1>; }; // Element const element = <Welcome name="John" />; // (Virtual) rendering ReactDOM.render( <Welcome name="John" />, document.getElementById('root') );
  17. Implementation of Flux. Predictable state container for JavaScript apps. •

    Single source of truth • Read only immutable state • Pure functional state changes • Flux compatible, less complex • Useful features ◦ Time travel ◦ Live Editing ◦ debugger ◦ middlewares Redux
  18. React-Redux Official React bindings for Redux: • connect function can

    map: ◦ state to props to React properties (mapping function, mapStateToProps, is a state “selector”) ◦ action dispatch to React properties (as function handlers) • - UI is a pure function of the state • When the state changes, if properties changed, a new rendering (of the virtual dom) is performed updating the view. CMP is an enhanced component (Container) that will re-render when props change. const CMP = connect(mapStateToProps, mapDispatchToProps)(Component);
  19. Redux Middlewares - Thunk Write action creators that return a

    function instead of an action. The thunk can be used to delay the dispatch of an action, or to dispatch only if a certain condition is met. The inner function receives the store methods dispatch and getState as parameters. • Pros: ◦ simple • Cons: ◦ no cancellation (if you use promises) ◦ no easy composition ◦ can not intercept actions ◦ complex async flows becomes hard to write and maintain Example 1: // action type export const INCREMENT_COUNTER = "INCREMENT_COUNTER" ; // action creator export function increment() { return { type: INCREMENT_COUNTER }; } // thunk export function delayIncrement () { return (dispatch) => { setTimeout(() => { dispatch(increment); // dispatches the action }, 1000); // after 1 second }; } // then the thunk function will be binded to the store, for instance with connect’s mapDispatchToProp, and called, for instance after a mouse click on some component.
  20. Redux Middlewares - Thunk Write action creators that return a

    function instead of an action. The thunk can be used to delay the dispatch of an action, or to dispatch only if a certain condition is met. The inner function receives the store methods dispatch and getState as parameters. • Pros: ◦ simple • Cons: ◦ no cancellation (if you use promises) ◦ no easy composition ◦ can not intercept actions ◦ complex async flows becomes hard to write and maintain Example 2: // action type export const RESULTS_RECEIVED = "RESULTS_RECEIVED" ; // action creator export function resultReceived (data) { return { type: RESULTS_RECEIVED , data }; } // thunk export function doRequest(url) { return (dispatch) => { axios .get(url).then((data) => { dispatch(resultReceived (data)); }); }; } // then the thunk function will be binded to the store, for insance with connect mapDispatchToProp, and called, for instance after a mouse click on some component.
  21. Redux Middlewares - Redux Observable Compose and cancel async actions

    to create side effects and more. • Pros: ◦ less code ◦ declarative ◦ allow easy cancellation with rollback ◦ complex flows becomes easy • Cons: ◦ Need to learn RxJS Dedicated section of the course here. Example: // actions file const PING = 'PING'; const PONG = 'PONG'; const ping = () => ({type: PING}); // implicit return const pong = () => ({type: PONG}); // epics file const pingEpic = actions$ => actions$ .ofType(PING) .delay(1000) .mapTo(pong());
  22. Resources • EcmaScript6: http://es6-features.org/ • React: https://facebook.github.io/react/ • Redux: http://redux.js.org/

    • React-Redux: https://redux.js.org/faq/react-redux • Redux Observable: https://redux-observable.js.org • Redux Observable for MapStore 2 developers: • https://docs.google.com/presentation/d/1Ts-yZGc12VMr9oG8xMqwptUmMj dsKI2uZh4Mr5shYhA/edit • MapStore 2 Dev guide: https://mapstore.readthedocs.io/en/latest/developer-guide/