Use ReasonML in your React applications (RuhrJS 2018)

Use ReasonML in your React applications (RuhrJS 2018)

6b50fbb7ade3c6b576b2c2b8ed4b0f7d?s=128

David Kopal

October 14, 2018
Tweet

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