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. JavaScript developer
    friendly syntax

    View full-size slide

  2. let meaningOfLife = 41 + 1;

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  6. OCaml semantics

    View full-size slide

  7. Reason Syntax OCaml Syntax
    OCaml AST

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  12. Compiles to JavaScript

    View full-size slide

  13. Reason Syntax OCaml Syntax
    OCaml AST
    JavaScript
    BuckleScript

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  17. Statically Typed Language

    View full-size slide

  18. Why yet another one?

    View full-size slide

  19. 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 full-size slide

  20. 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 full-size slide

  21. 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 full-size slide

  22. 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 full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  27. 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 full-size slide

  28. 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 full-size slide

  29. 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 full-size slide

  30. Pattern Matching

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  34. 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 full-size slide

  35. 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 full-size slide

  36. 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 full-size slide

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

    View full-size slide

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

    View full-size slide

  39. Lesson II
    Null is BAD!

    View full-size slide

  40. null; // doesn't exist!

    View full-size slide

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

    View full-size slide

  42. 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 full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  46. 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 full-size slide

  47. 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 full-size slide

  48. 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 full-size slide

  49. type state = {count: int};

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  53. 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 full-size slide

  54. 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 full-size slide

  55. 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 full-size slide

  56. 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 full-size slide

  57. Manage your State with GraphQL

    View full-size slide

  58. Interop with JavaScript

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  61. Variants to the rescue!

    View full-size slide

  62. [@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 full-size slide

  63. So what now?

    View full-size slide

  64. Don’t be that person

    View full-size slide

  65. Time
    Innovation
    React Ecosystem

    View full-size slide

  66. Time
    Innovation
    React Ecosystem
    Reason Ecosystem

    View full-size slide

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

    View full-size slide