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

The missing R in React

The missing R in React

A brief introduction to ReasonML and Reason React

Mateusz Zatorski

July 17, 2018
Tweet

More Decks by Mateusz Zatorski

Other Decks in Programming

Transcript

  1. (R)

  2. - func<onal - established language - compiled to: bytecode, fast

    na<ve or JavaScript - full-featured type system Why OCaml?
  3. OCaml syntax OCaml seman<cs Bytecode Na<ve Compiler backend replaced by

    BuckleScript OCaml syntax OCaml seman<cs BuckleScript
  4. Where we are at today? - syntax familiar to JS

    developers - full power of OCaml - clean and readable JS output
  5. Reason CLI global binaries needed by editor plugins Comes with

    a few extra tools: - refmt - “Reason format” - PreQer was inspired by refmt - merlin - engine powering type hint, refactor, 
 real-<me errors, jump to defini<ons, etc. 
 to our editors. - REPL - called rtop, interac<vely evaluates code - re:bench - online benchmarking playground - Redex - the Reason packages registry - ocamlc, ocamlopt, ocamlrun - bare ocaml compilers
  6. Strings “Hello world” Characters ‘a’ Integers 27 -13 Floats 27.0

    -13.0 Integer addiMon 27 + 13 Float addiMon 27.0 +. 13.0 Integer division/mulMplicaMon 14 / 2 * 8 Float division/mulMplicaMon 14.0 /. 2.0 *. 8.0 Float exponenMaMon 3.0 ** 3.0 String concatenaMon “Hello ” ++ “world”
  7. Comparison > < >= <= Boolean operaMons ! && ||

    Reference, physical (deep) equality === == Immutable lists [3, 2, 1] Arrays [|1, 2, 3|] Records type person = {age: int}; {age: 18} Comments /* my comment */
  8. Tuple type let coordinates: (float, float) = (48.0, -120.0); let

    xCoordinate = getX(coordinates); let yCoordinate = getY(coordinates);
  9. Record type access the individual fields in a record using

    the . operator: type person = { name: string, age: int, }; let matt = {name: "Mateusz", age: 12}; matt.name; /* "Mateusz" */ matt.age; /* 12 */
  10. Variant type Enumerated type type shoesColor = | Red |

    Blue | Green | Black; type month = | Name(string) | Num(int); let myMonth = Name("February"); let someOtherMonth = Num(3); Union type
  11. Variant type Recursive type type intTree = | Empty /*

    atomic */ | Node(int, intTree, intTree); /* compound */
  12. Polymorphic type type list('a) = | Nil | Cons('a, list(‘a));

    type stringList = list(string); let myList = Cons("foo", Cons("bar", Cons("baz", Nil))); Singly-linked list “foo” “bar” “baz” Nil
  13. Op<on type type option('a) = | None | Some('a); let

    division = (a: int, b: int) : option(int) => if (b === 0) { None; } else { Some(a / b); }; let myLuckyNumber = division(23, 45);
  14. let let hardMath = { let x = 4; let

    y = x - 1; x + y }; x and y are not accessible outside of hardMath scope let rec factorial = n => if (n === 0) { 1; } else { n * factorial(n - 1); };
  15. if-else let min = (x, y) => if (x <

    y) { x; } else { y; };
  16. if-else let min = (x, y) => if (x <

    y) { x; } else { y; }; let min = (x, y) => switch(x < y) { | true => x | false => y };
  17. Labelled arguments let add = (~x, ~y) => {/* use

    x and y here */}; add(~y=5, ~x=6);
  18. Currying let add = (x, y) => x + y;

    let inc = add(1); inc(10); /* 11 */
  19. Recursive func<ons let rec factorial = n => if (n

    === 0) { 1; } else { n * factorial(n - 1); };
  20. Modules module Calc = { let add = (x, y)

    => x + y; }; Calc.add(4, 5);
  21. Promises let fetchData = somePromise => somePromise |> Js.Promise.then_(value =>

    { Js.log(value); Js.Promise.resolve(value + 8); }) |> Js.Promise.catch(error => { Js.log("Error!!", error); Js.Promise.resolve(-2); });
  22. JavaScript interop let jsCalculate: (array(int), int) => int = [%bs.raw

    {| function (numbers, scaleFactor) { var result = 0; numbers.forEach(number => { result += number; }); return result * scaleFactor; } |} ]; let calculate = (numbers, scaleFactor) => jsCalculate(Array.of_list(numbers), scaleFactor); Js.log(calculate([1, 2, 3], 10)); /* -> 60 */
  23. Component let component = ReasonReact.statelessComponent("App"); let make = _children =>

    { ...component, render: _self => <div> <h1> (ReasonReact.string("Welcome!")) </h1> </div>, };
  24. Component let component = ReasonReact.statelessComponent(“App"); let make = (~message, _children)

    => { ...component, render: _self => <div> (ReasonReact.string(message)) </div>, };
  25. Component let component = ReasonReact.statelessComponent("App"); let make = (~fooProp, ~barProp,

    _children) => { ...component, /* render and lifecycle methods go here */ };
  26. type state = {isEnabled: bool}; type action = | Click;

    let component = ReasonReact.reducerComponent("App"); let make = _children => { ...component, initialState: () => {isEnabled: true}, reducer: (action, state) => switch (action) { | Click => ReasonReact.Update({isEnabled: ! state.isEnabled}) }, render: self => <div> <h1 onClick=(_event => self.send(Click))> (ReasonReact.string(self.state.isEnabled ? "on" : "off")) </h1> </div>, };
  27. type state = {isEnabled: bool}; type action = | Click;

    let component = ReasonReact.reducerComponent("App"); let make = _children => { ...component, initialState: () => {isEnabled: true}, reducer: (action, state) => switch (action) { | Click => ReasonReact.Update({isEnabled: ! state.isEnabled}) }, render: self => <div> <h1 onClick=(_event => self.send(Click))> (ReasonReact.string(self.state.isEnabled ? "on" : "off")) </h1> </div>, };
  28. type state = {isEnabled: bool}; type action = | Click;

    let component = ReasonReact.reducerComponent("App"); let make = _children => { ...component, initialState: () => {isEnabled: true}, reducer: (action, state) => switch (action) { | Click => ReasonReact.Update({isEnabled: ! state.isEnabled}) }, render: self => <div> <h1 onClick=(_event => self.send(Click))> (ReasonReact.string(self.state.isEnabled ? "on" : "off")) </h1> </div>, };
  29. type state = {isEnabled: bool}; type action = | Click;

    let component = ReasonReact.reducerComponent("App"); let make = _children => { ...component, initialState: () => {isEnabled: true}, reducer: (action, state) => switch (action) { | Click => ReasonReact.Update({isEnabled: ! state.isEnabled}) }, render: self => <div> <h1 onClick=(_event => self.send(Click))> (ReasonReact.string(self.state.isEnabled ? "on" : "off")) </h1> </div>, };
  30. type state = {isEnabled: bool}; type action = | Click;

    let component = ReasonReact.reducerComponent("App"); let make = _children => { ...component, initialState: () => {isEnabled: true}, reducer: (action, state) => switch (action) { | Click => ReasonReact.Update({isEnabled: ! state.isEnabled}) }, render: self => <div> <h1 onClick=(_event => self.send(Click))> (ReasonReact.string(self.state.isEnabled ? "on" : "off")) </h1> </div>, };
  31. type state = {isEnabled: bool}; type action = | Click;

    let component = ReasonReact.reducerComponent("App"); let make = _children => { ...component, initialState: () => {isEnabled: true}, reducer: (action, state) => switch (action) { | Click => ReasonReact.Update({isEnabled: ! state.isEnabled}) }, render: self => <div> <h1 onClick=(_event => self.send(Click))> (ReasonReact.string(self.state.isEnabled ? "on" : "off")) </h1> </div>, };
  32. type state = {isEnabled: bool}; type action = | Click;

    let component = ReasonReact.reducerComponent("App"); let make = _children => { ...component, initialState: () => {isEnabled: true}, reducer: (action, state) => switch (action) { | Click => ReasonReact.Update({isEnabled: ! state.isEnabled}) }, render: self => <div> <h1 onClick=(_event => self.send(Click))> (ReasonReact.string(self.state.isEnabled ? "on" : "off")) </h1> </div>, };
  33. type state = {isEnabled: bool}; type action = | Click;

    let component = ReasonReact.reducerComponent("App"); let make = _children => { ...component, initialState: () => {isEnabled: true}, reducer: (action, state) => switch (action) { | Click => ReasonReact.Update({isEnabled: ! state.isEnabled}) }, render: self => <div> <h1 onClick=(_event => self.send(Click))> (ReasonReact.string(self.state.isEnabled ? "on" : "off")) </h1> </div>, };
  34. type person = { name: string, age: int, }; let

    people: array(person) = [| {name: "Matt", age: 26}, {name: "Czysty", age: 6}, |]; Arrays
  35. type person = { name: string, age: int, }; let

    people: array(person) = [| {name: "Matt", age: 26}, {name: "Czysty", age: 6}, |]; let component = ReasonReact.statelessComponent("App"); let make = _children => { ...component, render: _self => <div> ( ReasonReact.array( Array.map( (person: person) => <p> (ReasonReact.string(person.name)) </p>, people, ), ) ) </div>, };
  36. type person = { name: string, age: int, }; let

    people: array(person) = [| {name: "Matt", age: 26}, {name: "Czysty", age: 6}, |]; let component = ReasonReact.statelessComponent("App"); let make = _children => { ...component, render: _self => <div> ( people |> Array.map((person: person) => <p> (ReasonReact.string(person.name)) </p> ) |> ReasonReact.array ) </div>, };
  37. Install reason-cli npm install -g [email protected] Install bs-pla\orm npm install

    -g bs-platform Add reason plugin to your editor vscode-reasonml
  38. reason-react bsb -init my-react-app -theme react cd my-react-app && npm

    install && npm start # in another tab npm run webpack