$30 off During Our Annual Pro Sale. View Details »

Use ReasonML in your React applications (RuhrJS 2018)

Use ReasonML in your React applications (RuhrJS 2018)

David Kopal

October 14, 2018
Tweet

More Decks by David Kopal

Other Decks in Programming

Transcript

  1. ÷÷÷÷÷÷≥≥≥ Use ReasonML in your React applications David Kopal

  2. @coding_lawyer @coding_lawyer codinglawyer.io meetup organizer contributor I’m David Kopal

  3. @coding_lawyer

  4. @coding_lawyer Who heard about ason?

  5. @coding_lawyer

  6. @coding_lawyer Who wants to write better React?

  7. @coding_lawyer React isn’t a native JavaScript library

  8. @coding_lawyer

  9. @coding_lawyer Immutability

  10. @coding_lawyer Immutability

  11. @coding_lawyer Immutability

  12. @coding_lawyer Immutability Functional programming

  13. @coding_lawyer Immutability Functional programming

  14. @coding_lawyer Immutability Functional programming

  15. @coding_lawyer Immutability Type system Functional programming

  16. @coding_lawyer Immutability Type system Functional programming

  17. @coding_lawyer Immutability Type system Functional programming

  18. @coding_lawyer Immutability Type system Functional programming

  19. @coding_lawyer Immutability Type system Functional programming

  20. @coding_lawyer Immutability Type system Functional programming

  21. @coding_lawyer Immutability Type system Functional programming

  22. @coding_lawyer

  23. @coding_lawyer semantics familiar syntax

  24. @coding_lawyer let fizzbuzz = (i) => switch (i mod 3,

    i mod 5) { | (0, 0) => "FizzBuzz" | (0, _) => "Fizz" | (_, 0) => "Buzz" | _ => string_of_int(i) }; for (i in 1 to 100) { Js.log(fizzbuzz(i)) };
  25. @coding_lawyer compiler

  26. @coding_lawyer function fizzbuzz(i) { var match = i % 3

    var match$1 = i % 5 if (match !== 0) { if (match$1 !== 0) { return String(i) } else { return 'Buzz' } } else if (match$1 !== 0) { return 'Fizz' } else { return 'FizzBuzz' } } for (var i = 1; i <= 100; ++i) { console.log(fizzbuzz(i)) } let fizzbuzz = (i) => switch (i mod 3, i mod 5) { | (0, 0) => "FizzBuzz" | (0, _) => "Fizz" | (_, 0) => "Buzz" | _ => string_of_int(i) }; for (i in 1 to 100) { Js.log(fizzbuzz(i)) };
  27. @coding_lawyer JavaScript interop

  28. @coding_lawyer

  29. @coding_lawyer Reason is compatible with React

  30. @coding_lawyer Reason is compatible with React React was developed for

    Reason
  31. @coding_lawyer adjusted JavaScript to React’s needs

  32. @coding_lawyer

  33. @coding_lawyer

  34. @coding_lawyer

  35. @coding_lawyer

  36. @coding_lawyer

  37. @coding_lawyer

  38. @coding_lawyer

  39. @coding_lawyer

  40. @coding_lawyer semantics familiar syntax

  41. @coding_lawyer safer React

  42. @coding_lawyer “[Reason] is the best way to take React to

    the next level” Jordan Walke, creator of Reason, React
  43. @coding_lawyer Tic Tac Toe github.com/codinglawyer/reason-tic-tac-toe

  44. @coding_lawyer

  45. @coding_lawyer

  46. @coding_lawyer

  47. @coding_lawyer

  48. @coding_lawyer Game Board App BoardRow Square

  49. @coding_lawyer Game Board App BoardRow Square

  50. @coding_lawyer Game Board App BoardRow Square

  51. @coding_lawyer Game Board App BoardRow Square

  52. @coding_lawyer Game Board App BoardRow Square

  53. @coding_lawyer Game Board App BoardRow Square

  54. @coding_lawyer components

  55. @coding_lawyer stateless component

  56. @coding_lawyer Game Board App BoardRow Square

  57. @coding_lawyer let component = ReasonReact.statelessComponent("App"); let make = _children =>

    { ...component, render: _self => <div> <div className=“title"> (ReasonReact.string("Tic Tac Toe")) </div> <Game /> </div>, };
  58. @coding_lawyer let component = ReasonReact.statelessComponent("App"); let make = _children =>

    { ...component, render: _self => <div> <div className="title"> (ReasonReact.string("Tic Tac Toe")) </div> <Game /> </div>, };
  59. @coding_lawyer let component = ReasonReact.statelessComponent("App"); let make = _children =>

    { ...component, render: _self => <div> <div className="title"> (ReasonReact.string("Tic Tac Toe")) </div> <Game /> </div>, };
  60. @coding_lawyer let component = ReasonReact.statelessComponent("App"); let make = _children =>

    { ...component, render: _self => <div> <div className="title"> (ReasonReact.string("Tic Tac Toe")) </div> <Game /> </div>, };
  61. @coding_lawyer let component = ReasonReact.statelessComponent("App"); let make = _children =>

    { ...component, render: _self => <div> <div className=“title"> (ReasonReact.string("Tic Tac Toe")) </div> <Game /> </div>, };
  62. @coding_lawyer reducer component

  63. @coding_lawyer Game Board App BoardRow Square

  64. @coding_lawyer let component = ReasonReact.reducerComponent("Game"); let make = _children =>

    { ...component, initialState: () => { board: […], gameState:… }, reducer: (action: action, state: state) => switch (action) { | Restart => … | ClickSquare((id: string)) => … }, render: ({state, send}) => <div className="game"> <Board state onRestart=(_evt => send(Restart)) onMark=(id => send(ClickSquare(id))) /> </div>, };
  65. @coding_lawyer let component = ReasonReact.reducerComponent("Game"); let make = _children =>

    { ...component, initialState: () => { board: […], gameState:… }, reducer: (action: action, state: state) => switch (action) { | Restart => … | ClickSquare((id: string)) => … }, render: ({state, send}) => <div className="game"> <Board state onRestart=(_evt => send(Restart)) onMark=(id => send(ClickSquare(id))) /> </div>, };
  66. @coding_lawyer let component = ReasonReact.reducerComponent("Game"); let make = _children =>

    { ...component, initialState: () => { board: […], gameState:… }, reducer: (action: action, state: state) => switch (action) { | Restart => … | ClickSquare((id: string)) => … }, render: ({state, send}) => <div className="game"> <Board state onRestart=(_evt => send(Restart)) onMark=(id => send(ClickSquare(id))) /> </div>, };
  67. @coding_lawyer let component = ReasonReact.reducerComponent("Game"); let make = _children =>

    { ...component, initialState: () => { board: […], gameState:… }, reducer: (action: action, state: state) => switch (action) { | Restart => … | ClickSquare((id: string)) => … }, render: ({state, send}) => <div className="game"> <Board state onRestart=(_evt => send(Restart)) onMark=(id => send(ClickSquare(id))) /> </div>, };
  68. @coding_lawyer let component = ReasonReact.reducerComponent("Game"); let make = _children =>

    { ...component, initialState: () => { board: […], gameState:… }, reducer: (action: action, state: state) => switch (action) { | Restart => … | ClickSquare((id: string)) => … }, render: ({state, send}) => <div className="game"> <Board state onRestart=(_evt => send(Restart)) onMark=(id => send(ClickSquare(id))) /> </div>, };
  69. @coding_lawyer let component = ReasonReact.reducerComponent("Game"); let make = _children =>

    { ...component, initialState: () => { board: […], gameState:… }, reducer: (action: action, state: state) => switch (action) { | Restart => … | ClickSquare((id: string)) => … }, render: ({state, send}) => <div className="game"> <Board state onRestart=(_evt => send(Restart)) onMark=(id => send(ClickSquare(id))) /> </div>, };
  70. @coding_lawyer let component = ReasonReact.reducerComponent("Game"); let make = _children =>

    { ...component, initialState: () => { board: […], gameState:… }, reducer: (action: action, state: state) => switch (action) { | Restart => … | ClickSquare((id: string)) => … }, render: ({state, send}) => <div className="game"> <Board state onRestart=(_evt => send(Restart)) onMark=(id => send(ClickSquare(id))) /> </div>, };
  71. @coding_lawyer let component = ReasonReact.reducerComponent("Game"); let make = _children =>

    { ...component, initialState: () => { board: […], gameState:… }, reducer: (action: action, state: state) => switch (action) { | Restart => … | ClickSquare((id: string)) => … }, render: ({state, send}) => <div className="game"> <Board state onRestart=(_evt => send(Restart)) onMark=(id => send(ClickSquare(id))) /> </div>, };
  72. @coding_lawyer let component = ReasonReact.reducerComponent("Game"); let make = _children =>

    { ...component, initialState: () => { board: […], gameState:… }, reducer: (action: action, state: state) => switch (action) { | Restart => … | ClickSquare((id: string)) => … }, render: ({state, send}) => <div className="game"> <Board state onRestart=(_evt => send(Restart)) onMark=(id => send(ClickSquare(id))) /> </div>, };
  73. @coding_lawyer Game Board App BoardRow Square

  74. @coding_lawyer Game Board App BoardRow Square

  75. @coding_lawyer Game Board App BoardRow Square

  76. @coding_lawyer Game Board App BoardRow Square

  77. @coding_lawyer Game Board App BoardRow Square

  78. @coding_lawyer Game Board App BoardRow Square

  79. @coding_lawyer Game Board App BoardRow Square

  80. @coding_lawyer let component = ReasonReact.reducerComponent("Game"); let make = _children =>

    { ...component, initialState: () => { board: […], gameState:… }, reducer: (action: action, state: state) => switch (action) { | Restart => … | ClickSquare((id: string)) => … }, render: ({state, send}) => <div className="game"> <Board state onRestart=(_evt => send(Restart)) onMark=(id => send(ClickSquare(id))) /> </div>, };
  81. @coding_lawyer let component = ReasonReact.reducerComponent("Game"); let make = _children =>

    { ...component, initialState: () => { board: […], gameState:… }, reducer: (action: action, state: state) => switch (action) { | Restart => … | ClickSquare((id: string)) => … }, render: ({state, send}) => <div className="game"> <Board state onRestart=(_evt => send(Restart)) onMark=(id => send(ClickSquare(id))) /> </div>, };
  82. @coding_lawyer reducer: (action: action, state: state) => switch (action) {

    | Restart => ReasonReact.Update(initialState) | ClickSquare((id: string)) => let updatedBoard = updateBoard( state.board, state.gameState, id); let updatedGs = checkGameState3x3( updatedBoard, state.board, state.gameState); ReasonReact.Update({ board: updatedBoard, gameState: updatedGs, }); },
  83. @coding_lawyer reducer: (action: action, state: state) => switch (action) {

    | Restart => ReasonReact.Update(initialState) | ClickSquare((id: string)) => let updatedBoard = updateBoard( state.board, state.gameState, id); let updatedGs = checkGameState3x3( updatedBoard, state.board, state.gameState); ReasonReact.Update({ board: updatedBoard, gameState: updatedGs, }); },
  84. @coding_lawyer reducer: (action: action, state: state) => switch (action) {

    | Restart => ReasonReact.Update(initialState) | ClickSquare((id: string)) => let updatedBoard = updateBoard( state.board, state.gameState, id); let updatedGs = checkGameState3x3( updatedBoard, state.board, state.gameState); ReasonReact.UpdateWithSideEffects( { board: updatedBoard, gameState: updatedGs, }, (_self => Js.log(“Clicked")), ); },
  85. @coding_lawyer pure state update and side-effects separation

  86. @coding_lawyer less boilerplate

  87. @coding_lawyer Redux’s principles and component’s reusability

  88. @coding_lawyer type system

  89. @coding_lawyer clearer and safer code

  90. @coding_lawyer superior to Flow and TypeScript

  91. @coding_lawyer type inference

  92. @coding_lawyer !/* type inference by the compiler !*/ let plus

    = (a, b) !=> a + b
  93. @coding_lawyer !/* type inference by the compiler !*/ let plus

    = (a, b) !=> a + b !/* (int, int) !=> int !*/
  94. @coding_lawyer type field = | Empty | Marked(player); type gameState

    = | Playing(player) | Winner(player) | Draw; type player = | Cross | Circle;
  95. @coding_lawyer type field = | Empty | Marked(player); type gameState

    = | Playing(player) | Winner(player) | Draw; type player = | Cross | Circle;
  96. @coding_lawyer type field = | Empty | Marked(player); type gameState

    = | Playing(player) | Winner(player) | Draw; type player = | Cross | Circle;
  97. @coding_lawyer type field = | Empty | Marked(player); type gameState

    = | Playing(player) | Winner(player) | Draw; type player = | Cross | Circle;
  98. @coding_lawyer type field = | Empty | Marked(player); type gameState

    = | Playing(player) | Winner(player) | Draw; type player = | Cross | Circle;
  99. @coding_lawyer

  100. @coding_lawyer pattern matching

  101. @coding_lawyer Game Board App BoardRow Square

  102. @coding_lawyer reducer: (action: action, state: state) => switch (action) {

    | Restart => ReasonReact.Update(initialState) | ClickSquare((id: string)) => let updatedBoard = updateBoard( state.board, state.gameState, id); let updatedGs = checkGameState3x3( updatedBoard, state.board, state.gameState); ReasonReact.Update({ board: updatedBoard, gameState: updatedGs, }); },
  103. @coding_lawyer let updateBoard = (board: board, gameState: gameState, id) =>

    board |> List.mapi((ind: int, row: row) => row |> List.mapi((index: int, value: field) => string_of_int(ind) ++ string_of_int(index) === id ? switch (gameState, value) { | (Playing(_), Marked(_)) => value | (Playing(player), Empty) => Marked(player) | (_, _) => Empty } : value ) );
  104. @coding_lawyer let updateBoard = (board: board, gameState: gameState, id) =>

    board |> List.mapi((ind: int, row: row) => row |> List.mapi((index: int, value: field) => string_of_int(ind) ++ string_of_int(index) === id ? switch (gameState, value) { | (Playing(_), Marked(_)) => value | (Playing(player), Empty) => Marked(player) | (_, _) => Empty } : value ) );
  105. @coding_lawyer type field = | Empty | Marked(player); type gameState

    = | Playing(player) | Winner(player) | Draw;
  106. @coding_lawyer /* determines the value of the clicked square */

    switch (gameState: gameState, value: field) { | (Playing(_), Marked(_)) => value | (Playing(player), Empty) => Marked(player) | (_, _) => Empty }
  107. @coding_lawyer /* determines the value of the clicked square */

    switch (gameState: gameState, value: field) { | (Playing(_), Marked(_)) => value | (Playing(player), Empty) => Marked(player) | (_, _) => Empty }
  108. @coding_lawyer /* determines the value of the clicked square */

    switch (gameState: gameState, value: field) { | (Playing(_), Marked(_)) => value | (Playing(player), Empty) => Marked(player) | (_, _) => Empty }
  109. @coding_lawyer /* determines the value of the clicked square */

    switch (gameState: gameState, value: field) { | (Playing(_), Marked(_)) => value | (Playing(player), Empty) => Marked(player) | (_, _) => Empty }
  110. @coding_lawyer /* determines the value of the clicked square */

    switch (gameState: gameState, value: field) { | (Playing(_), Marked(_)) => value | (Playing(player), Empty) => Marked(player) | (_, _) => Empty }
  111. @coding_lawyer /* determines the value of the clicked square */

    switch (gameState: gameState, value: field) { | (Playing(_), Marked(_)) => value | (Playing(player), Empty) => Marked(player) | (_, _) => Empty }
  112. @coding_lawyer /* determines the value of the clicked square */

    switch (gameState: gameState, value: field) { | (Playing(_), Marked(_)) => value | (Playing(player), Empty) => Marked(player) | (_, _) => Empty }
  113. @coding_lawyer /* determines the value of the clicked square */

    switch (gameState: gameState, value: field) { | (Playing(_), Marked(_)) => value | (Playing(player), Empty) => Marked(player) /* | (_, _) => Empty */ }
  114. @coding_lawyer

  115. @coding_lawyer switch ( getWinner(flattenBoard, head), gameEnded(flattenBoard), tail, ) { |

    (Cross, _, _) => Winner(Cross) | (Circle, _, _) => Winner(Circle) | (_, true, []) => Draw | (_, false, []) => whosPlaying(gameState) | _ => check(tail) };
  116. @coding_lawyer switch (match$1) { case 0 : return /* Winner

    */Block.__(1, [/* Cross */0]); case 1 : return /* Winner */Block.__(1, [/* Circle */1]); case 2 : if (match$2) { if (tail) { _rest = tail; continue ; } else { return /* Draw */0; } } else if (tail) { _rest = tail; continue ; } else { return whosPlaying(gameState); } }
  117. @coding_lawyer Why should you use React in Reason?

  118. @coding_lawyer Reason is compatible with React's principles

  119. @coding_lawyer strong type system

  120. @coding_lawyer pattern matching

  121. @coding_lawyer functional programming features

  122. @coding_lawyer stateless and stateful component separation

  123. @coding_lawyer JavaScript-like syntax React friendly

  124. @coding_lawyer Get your hands dirty! sketch.sh

  125. @coding_lawyer 
 codinglawyer.io @coding_lawyer

  126. @coding_lawyer Thank You

  127. @coding_lawyer @coding_lawyer codinglawyer.io github.com/codinglawyer/reason-tic-tac-toe