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

Get started with Reason

Get started with Reason

We will kick off with the basics and then quickly go into how to leverage features like variant types and pattern matching to make impossible states impossible. After you gained some knowledge about the basics the course will dig even further into ReasonReact.

Nikolaus Graf

April 26, 2018
Tweet

More Decks by Nikolaus Graf

Other Decks in Programming

Transcript

  1. View Slide

  2. View Slide

  3. JavaScript developer
    friendly syntax

    View Slide

  4. let meaningOfLife = 41 + 1;

    View Slide

  5. let add = (x, y) => x + y;
    add(2, 2);
    add(41, 1);

    View Slide

  6. let fruits = ["Apple", "Orange"];

    View Slide

  7. if (true) {
    print_string("Hello World!");
    };

    View Slide

  8. OCaml semantics

    View Slide

  9. Reason Syntax OCaml Syntax
    OCaml AST

    View Slide

  10. Records

    View Slide

  11. let jane = {name: "Jane", age: 40};

    View Slide

  12. let jane = {name: "Jane", age: 40};

    View Slide

  13. type person = {
    name: string,
    age: int,
    };
    let jane = {name: "Jane", age: 40};

    View Slide

  14. type person = {
    name: string,
    age: int,
    };
    let jane = {name: "Jane", age: 40};
    let tim = {...jane, name: "Tim"};

    View Slide

  15. Compiles to JavaScript

    View Slide

  16. Reason Syntax OCaml Syntax
    OCaml AST
    JavaScript
    BuckleScript

    View Slide

  17. Reason Syntax OCaml Syntax
    OCaml AST
    Native Code JavaScript
    BuckleScript

    View Slide

  18. Fromatter

    View Slide

  19. Reason Syntax OCaml Syntax
    OCaml AST
    Native Code JavaScript
    BuckleScript

    View Slide

  20. Reason Syntax OCaml Syntax
    OCaml AST
    Native Code JavaScript
    refmt
    BuckleScript

    View Slide

  21. Statically Typed Language

    View Slide

  22. View Slide

  23. Why yet another one?

    View Slide

  24. View Slide

  25. const pieces = [
    { kind: "king", color: "black", position: [3, 4] },
    { kind: "pawn", color: "black", position: [4, 2] },
    { kind: "knight", color: "white", position: [3, 3] }
    ];
    JavaScript

    View Slide

  26. interface Piece {
    kind: string;
    color: string;
    position: number[];
    }
    const pieces = [
    { kind: "king", color: "black", position: [3, 4] },
    { kind: "pawn", color: "black", position: [4, 2] },
    { kind: "knight", color: "white", position: [3, 3] }
    ];
    const getKinds = (pieces: Piece[]) => pieces.map(piece => piece.kind);
    TypeScript

    View Slide

  27. interface Piece {
    kind: string;
    color: string;
    position: number[];
    }
    const pieces = [
    { kind: "king", color: "black", position: [3, 4] },
    { kind: "pawn", color: "black", position: [4, 2] },
    { kind: "knight", color: "white", position: [3, 3] }
    ];
    const getKinds = (pieces: Piece[]) => pieces.map(piece => piece.kind);
    TypeScript

    View Slide

  28. type piece = {
    kind: string,
    color: string,
    position: (int, int),
    };
    let pieces = [
    {kind: "king", color: "black", position: (3, 4)},
    {kind: "pawn", color: "black", position: (4, 2)},
    {kind: "knight", color: "white", position: (3, 3)},
    ];
    let getKinds = pieces => List.map(item => item.kind, pieces);
    Reason

    View Slide

  29. Variants

    View Slide

  30. type direction =
    | Up
    | Down
    | Left
    | Right;

    View Slide

  31. type direction =
    | Up
    | Down
    | Left
    | Right;
    let move = Left;

    View Slide

  32. type direction =
    | Up(int)
    | Down(int)
    | Left(int)
    | Right(int);
    let move = Left(2);

    View Slide

  33. type data = {names: list(string)};
    type request =
    | Loading
    | Error(int)
    | Success(data);

    View Slide

  34. type color = Black | White;
    type kind = Queen | King | Rook | Bishop | Knight | Pawn;
    type piece = {
    color,
    kind,
    position: (int, int),
    };
    let pieces = [
    {kind: King, color: Black, position: (3, 4)},
    {kind: Pawn, color: Black, position: (4, 2)},
    {kind: Knight, color: White, position: (3, 3)},
    ];

    View Slide

  35. type color = Black | White;
    type kind = Queen | King | Rook | Bishop | Knight | Pawn;
    type piece = {
    color,
    kind,
    position: (int, int),
    };
    let pieces = [
    {kind: King, color: Black, position: (3, 4)},
    {kind: Pawn, color: Black, position: (4, 2)},
    {kind: Knight, color: White, position: (3, 3)},
    ];

    View Slide

  36. type color = Black | White;
    type kind = Queen | King | Rook | Bishop | Knight | Pawn;
    type piece = {
    color,
    kind,
    position: (int, int),
    };
    let pieces = [
    {kind: King, color: Black, position: (3, 4)},
    {kind: Pawn, color: Black, position: (4, 2)},
    {kind: Knight, color: White, position: (3, 3)},
    ];

    View Slide

  37. Pattern Matching

    View Slide

  38. switch () {
    | =>
    | =>
    | ...
    };

    View Slide

  39. switch (1) {
    | 0 => "off"
    | 1 => "on"
    | _ => "off"
    };

    View Slide

  40. let displayText =
    switch (1) {
    | 0 => "off"
    | 1 => "on"
    | _ => "off"
    };

    View Slide

  41. type data = {names: list(string)};
    type request =
    | Loading
    | Error(int)
    | Success(data);
    let ui =
    switch (Loading) {
    | Loading => "Loading ..."
    | Error(code) => "Something went wrong. Error: " ++ string_of_int(code)
    | Success(data) => List.fold_left((a, b) => a ++ b, "Names:", data.names)
    };

    View Slide

  42. type data = {names: list(string)};
    type request =
    | Loading
    | Error(int)
    | Success(data);
    let ui =
    switch (Loading) {
    | Loading => "Loading ..."
    | Error(401) => "You aren’t authenticated."
    | Error(code) => "Something went wrong. Error: " ++ string_of_int(code)
    | Success(data) => List.fold_left((a, b) => a ++ b, "Names:", data.names)
    };

    View Slide

  43. type data = {names: list(string)};
    type request =
    | Loading
    | Error(int)
    | Success(data);
    let ui =
    switch (Loading) {
    | Loading => "Loading ..."
    | Error(401 | 402) => "You aren’t authenticated."
    | Error(code) => "Something went wrong. Error: " ++ string_of_int(code)
    | Success(data) => List.fold_left((a, b) => a ++ b, "Names:", data.names)
    };

    View Slide

  44. View Slide

  45. – Tony Hoare
    “I call it my billion-dollar mistake …”

    View Slide

  46. View Slide

  47. View Slide

  48. Lesson I
    Don’t implement anything just
    because it’s easy!

    View Slide

  49. Lesson II
    Null is BAD!

    View Slide

  50. null; // doesn't exist!

    View Slide

  51. Option

    View Slide

  52. let foo = None;
    let foo = Some(42);
    let foo = Some([1, 2, 3]);
    let foo = Some("Hello World!");

    View Slide

  53. let foo = None;
    let foo = Some(42);
    let foo = Some([1, 2, 3]);
    let foo = Some("Hello World!");
    switch (foo) {
    | None => "Sadly I don't know."
    | Some(value) => "It's " ++ value
    };

    View Slide

  54. Functions

    View Slide

  55. let add = (x, y) => x + y;
    add(2, 2);
    add(41, 1);

    View Slide

  56. let name = (~firstName, ~lastName) => firstName ++ " " ++ lastName;
    /* Jane Doe */
    name(~firstName="Jane", ~lastName="Doe");
    /* Jane Doe */
    name(~lastName="Doe", ~firstName="Jane");

    View Slide

  57. ReasonReact

    View Slide

  58. Stateless Component
    let component = ReasonReact.statelessComponent("Greeting");
    let make = (_children) => {
    ...component,
    render: _self => (ReasonReact.string("Hello")),
    };
    ReactDOMRe.renderToElementWithId(, "root");
    Greeting.re
    App.re

    View Slide

  59. Props
    let component = ReasonReact.statelessComponent("Greeting");
    let make = (~name, _children) => {
    ...component,
    render: _self => (ReasonReact.string(“Hello " ++ name)),
    };
    ReactDOMRe.renderToElementWithId(, "root");
    Greeting.re
    App.re

    View Slide

  60. Props
    let component = ReasonReact.statelessComponent("Greeting");
    let make = (~name, _children) => {
    ...component,
    render: _self => (ReasonReact.string("Hello " ++ name)),
    };
    ReactDOMRe.renderToElementWithId(, "root");
    Greeting.re
    App.re

    View Slide

  61. Props
    let component = ReasonReact.statelessComponent("Greeting");
    let make = (~name, _children) => {
    ...component,
    render: _self => (ReasonReact.string("Hello " ++ name)),
    };
    ReactDOMRe.renderToElementWithId(, "root");
    Greeting.re
    App.re

    View Slide

  62. View Slide

  63. type state = {count: int};

    View Slide

  64. type state = {count: int};
    type action =
    | Add(int)
    | Reset;

    View Slide

  65. type state = {count: int};
    type action =
    | Add(int)
    | Reset;
    let s = ReasonReact.string;

    View Slide

  66. type state = {count: int};
    type action =
    | Add(int)
    | Reset;
    let s = ReasonReact.string;
    let component = ReasonReact.reducerComponent("Counter");

    View Slide

  67. type state = {count: int};
    type action =
    | Add(int)
    | Reset;
    let s = ReasonReact.string;
    let component = ReasonReact.reducerComponent("Counter");
    let make = _children => {
    ...component,
    initialState: () => {count: 0},

    View Slide

  68. type state = {count: int};
    type action =
    | Add(int)
    | Reset;
    let s = ReasonReact.string;
    let component = ReasonReact.reducerComponent("Counter");
    let make = _children => {
    ...component,
    initialState: () => {count: 0},
    reducer: (action, state) =>
    switch (action) {
    | Add(value) => ReasonReact.Update({count: state.count + value})
    | Reset => ReasonReact.Update({count: 0})
    },

    View Slide

  69. type state = {count: int};
    type action =
    | Add(int)
    | Reset;
    let s = ReasonReact.string;
    let component = ReasonReact.reducerComponent("Counter");
    let make = _children => {
    ...component,
    initialState: () => {count: 0},
    reducer: (action, state) =>
    switch (action) {
    | Add(value) => ReasonReact.Update({count: state.count + value})
    | Reset => ReasonReact.Update({count: 0})
    },
    render: self =>

    (s(string_of_int(self.state.count)))

    View Slide

  70. let s = ReasonReact.string;
    let component = ReasonReact.reducerComponent("Counter");
    let make = _children => {
    ...component,
    initialState: () => {count: 0},
    reducer: (action, state) =>
    switch (action) {
    | Add(value) => ReasonReact.Update({count: state.count + value})
    | Reset => ReasonReact.Update({count: 0})
    },
    render: self =>

    (s(string_of_int(self.state.count)))
    self.send(Add(1)))> (s(“Add"))
    self.send(Add(2)))> (s("Add 2"))
    self.send(Reset))> (s("Reset"))
    ,
    };

    View Slide

  71. View Slide

  72. Manage your State with GraphQL

    View Slide

  73. Interop with JavaScript

    View Slide

  74. BuckleScript allows us to write bindings
    ReasonReact
    - wrapJsForReason
    - wrapReasonForJs

    View Slide

  75. [@bs.module "rebass"] external jsArrow : ReasonReact.reactClass = "Arrow";
    let make = (~direction: string, children) =>
    ReasonReact.wrapJsForReason(
    ~reactClass=jsArrow,
    ~props={"direction": direction},
    children,
    );

    View Slide


  76. View Slide


  77. View Slide


  78. View Slide

  79. View Slide

  80. Variants to the rescue!

    View Slide

  81. [@bs.module "rebass"] external jsArrow : ReasonReact.reactClass = "Arrow";
    type direction =
    | Up
    | Down;
    let make = (~direction, children) => {
    let directionString =
    switch (direction) {
    | Up => "up"
    | Down => "down"
    };
    ReasonReact.wrapJsForReason(
    ~reactClass=jsArrow,
    ~props={"direction": directionString},
    children,
    );
    };

    View Slide

  82. ;

    View Slide

  83. ;

    View Slide

  84. ;

    View Slide

  85. So what now?

    View Slide

  86. Don’t be that person

    View Slide

  87. Time
    Innovation
    React Ecosystem

    View Slide

  88. Time
    Innovation
    React Ecosystem
    Reason Ecosystem

    View Slide

  89. Day 1: Workshop
    Day 2: Talks
    Day 3: Hackathon

    View Slide

  90. The End

    View Slide