Write better React (v3 ReasonReact)

Write better React (v3 ReasonReact)

6b50fbb7ade3c6b576b2c2b8ed4b0f7d?s=128

David Kopal

May 11, 2019
Tweet

Transcript

  1. Write better React with ReasonML David Kopal

  2. @coding_lawyer codinglawyer.io learnReasonML.com I’m David Kopal

  3. @coding_lawyer Who heard about ason?

  4. @coding_lawyer

  5. @coding_lawyer Who wants to write better React?

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

  7. @coding_lawyer

  8. @coding_lawyer Immutability

  9. @coding_lawyer Immutability

  10. @coding_lawyer Immutability

  11. @coding_lawyer Immutability Functional programming

  12. @coding_lawyer Immutability Functional programming

  13. @coding_lawyer Immutability Functional programming

  14. @coding_lawyer Immutability Type system 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

  22. @coding_lawyer semantics Javascript-like syntax

  23. @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)) };
  24. @coding_lawyer compiler

  25. @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)) };
  26. @coding_lawyer JavaScript interop

  27. @coding_lawyer

  28. @coding_lawyer Reason is compatible with React

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

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

  31. @coding_lawyer

  32. @coding_lawyer

  33. @coding_lawyer

  34. @coding_lawyer

  35. @coding_lawyer

  36. @coding_lawyer

  37. @coding_lawyer

  38. @coding_lawyer

  39. @coding_lawyer semantics Javascript-like syntax

  40. @coding_lawyer safer React

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

    the next level” Jordan Walke, creator of Reason, React
  42. @coding_lawyer Tic Tac Toe

  43. @coding_lawyer

  44. @coding_lawyer

  45. @coding_lawyer

  46. @coding_lawyer

  47. @coding_lawyer Game Board App BoardRow Square

  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 components

  54. @coding_lawyer stateless component

  55. @coding_lawyer Game Board App BoardRow Square

  56. @coding_lawyer [@react.component] let make = (~title) !=> <div> <div className=“title">

    {React.string(title)} !</div> <Game !/> !</div>;
  57. @coding_lawyer [@react.component] let make = (~title) !=> <div> <div className=“title">

    {React.string(title)} !</div> <Game !/> !</div>;
  58. @coding_lawyer [@react.component] let make = (~title) !=> <div> <div className=“title">

    {React.string(title)} !</div> <Game !/> !</div>;
  59. @coding_lawyer [@react.component] let make = (~title) !=> <div> <div className=“title">

    {React.string(title)} !</div> <Game !/> !</div>;
  60. @coding_lawyer stateful component

  61. @coding_lawyer Game Board App BoardRow Square

  62. @coding_lawyer [@react.component] let make = () !=> { let (state,

    dispatch) = React.useReducer( (state: state, action: action) !=> switch (action) { | Restart !=> … | ClickSquare((id: string)) !=> … }, { board: […], gameState: Playing(Cross) }, ); <div className="game"> <Board state onRestart={_evt !=> dispatch(Restart)} onMark={id !=> dispatch(ClickSquare(id))} !/> !</div>;};
  63. @coding_lawyer [@react.component] let make = () !=> { let (state,

    dispatch) = React.useReducer( (state: state, action: action) !=> switch (action) { | Restart !=> … | ClickSquare((id: string)) !=> … }, { board: […], gameState: Playing(Cross) }, ); <div className="game"> <Board state onRestart={_evt !=> dispatch(Restart)} onMark={id !=> dispatch(ClickSquare(id))} !/> !</div>;};
  64. @coding_lawyer [@react.component] let make = () !=> { let (state,

    dispatch) = React.useReducer( (state: state, action: action) !=> switch (action) { | Restart !=> … | ClickSquare((id: string)) !=> … }, { board: […], gameState: Playing(Cross) }, ); <div className="game"> <Board state onRestart={_evt !=> dispatch(Restart)} onMark={id !=> dispatch(ClickSquare(id))} !/> !</div>;};
  65. @coding_lawyer [@react.component] let make = () !=> { let (state,

    dispatch) = React.useReducer( (state: state, action: action) !=> switch (action) { | Restart !=> … | ClickSquare((id: string)) !=> … }, { board: […], gameState: Playing(Cross) }, ); <div className="game"> <Board state onRestart={_evt !=> dispatch(Restart)} onMark={id !=> dispatch(ClickSquare(id))} !/> !</div>;};
  66. @coding_lawyer [@react.component] let make = () !=> { let (state,

    dispatch) = React.useReducer( (state: state, action: action) !=> switch (action) { | Restart !=> … | ClickSquare((id: string)) !=> … }, { board: […], gameState: Playing(Cross) }, ); <div className="game"> <Board state onRestart={_evt !=> dispatch(Restart)} onMark={id !=> dispatch(ClickSquare(id))} !/> !</div>;};
  67. @coding_lawyer [@react.component] let make = () !=> { let (state,

    dispatch) = React.useReducer( (state: state, action: action) !=> switch (action) { | Restart !=> … | ClickSquare((id: string)) !=> … }, { board: […], gameState: Playing(Cross) }, ); <div className="game"> <Board state onRestart={_evt !=> dispatch(Restart)} onMark={id !=> dispatch(ClickSquare(id))} !/> !</div>;};
  68. @coding_lawyer [@react.component] let make = () !=> { let (state,

    dispatch) = React.useReducer( (state: state, action: action) !=> switch (action) { | Restart !=> … | ClickSquare((id: string)) !=> … }, { board: […], gameState: Playing(Cross) }, ); <div className="game"> <Board state onRestart={_evt !=> dispatch(Restart)} onMark={id !=> dispatch(ClickSquare(id))} !/> !</div>;};
  69. @coding_lawyer [@react.component] let make = () !=> { let (state,

    dispatch) = React.useReducer( (state: state, action: action) !=> switch (action) { | Restart !=> … | ClickSquare((id: string)) !=> … }, { board: […], gameState: Playing(Cross) }, ); <div className="game"> <Board state onRestart={_evt !=> dispatch(Restart)} onMark={id !=> dispatch(ClickSquare(id))} !/> !</div>;};
  70. @coding_lawyer Game Board App BoardRow Square

  71. @coding_lawyer Game Board App BoardRow Square

  72. @coding_lawyer Game Board App BoardRow Square

  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 [@react.component] let make = () !=> { let (state,

    dispatch) = React.useReducer( (state: state, action: action) !=> switch (action) { | Restart !=> … | ClickSquare((id: string)) !=> … }, { board: […], gameState: Playing(Cross) }, ); <div className="game"> <Board state onRestart={_evt !=> dispatch(Restart)} onMark={id !=> dispatch(ClickSquare(id))} !/> !</div>;};
  78. @coding_lawyer [@react.component] let make = () !=> { let (state,

    dispatch) = React.useReducer( (state: state, action: action) !=> switch (action) { | Restart !=> … | ClickSquare((id: string)) !=> … }, { board: […], gameState: Playing(Cross) }, ); <div className="game"> <Board state onRestart={_evt !=> dispatch(Restart)} onMark={id !=> dispatch(ClickSquare(id))} !/> !</div>;};
  79. @coding_lawyer React.useReducer( (state: state, action: action) !=> switch (action) {

    | Restart !=> initialState | ClickSquare((id: string)) !=> let updatedBoard = updateBoard( state.board, state.gameState, id); let updatedGs = checkGameState3x3( updatedBoard, state.board, state.gameState); { board: updatedBoard, gameState: updatedGs, };}, …);
  80. @coding_lawyer React.useReducer( (state: state, action: action) !=> switch (action) {

    | Restart !=> initialState | ClickSquare((id: string)) !=> let updatedBoard = updateBoard( state.board, state.gameState, id); let updatedGs = checkGameState3x3( updatedBoard, state.board, state.gameState); { board: updatedBoard, gameState: updatedGs, };}, …);
  81. @coding_lawyer [@react.component] let make = () !=> { let (state,

    dispatch) = React.useReducer( (state: state, action: action) !=> switch (action) { | Restart !=> … | ClickSquare((id: string)) !=> … }, { board: […], gameState: Playing(Cross) }, ); <div className="game"> <Board state onRestart={_evt !=> dispatch(Restart)} onMark={id !=> dispatch(ClickSquare(id))} !/> !</div>;};
  82. @coding_lawyer old syntax (v2) vs new syntax (v3)

  83. @coding_lawyer [@react.component] let make = (~title) !=> <div> <div className=“title">

    {React.string(title)} !</div> <Game !/> !</div>; new syntax (v3)
  84. @coding_lawyer let component = ReasonReact.statelessComponent("App"); let make = (~title, _children)

    => { ...component, render: _self => <div> <div className=“title"> (ReasonReact.string(title)) </div> <Game /> </div>, }; old syntax (v2)
  85. @coding_lawyer let component = ReasonReact.statelessComponent("App"); let make = (~title, _children)

    => { ...component, render: _self => <div> <div className=“title"> (ReasonReact.string(title)) </div> <Game /> </div>, }; old syntax (v2) var component = ReasonReact.statelessComponent("App"); function make(title, _children) { return !/* record !*/[ !/* debugName !*/component[!/* debugName !*/0], !/* reactClassInternal !*/component[!/* reactClassInternal !*/1] !/* handedOffState !*/component[!/* handedOffState !*/2], !/* willReceiveProps !*/component[!/* willReceiveProps !*/3], !/* didMount !*/component[!/* didMount !*/4], !/* didUpdate !*/component[!/* didUpdate !*/5], !/* willUnmount !*/component[!/* willUnmount !*/6], !/* willUpdate !*/component[!/* willUpdate !*/7], !/* shouldUpdate !*/component[!/* shouldUpdate !*/8], !/* render !*/(function (_self) { return React.createElement( “div", undefined, React.createElement( "div", { className: “title" }, title), React.createElement(Game.make, { }) ); }), !/* initialState !*/component[!/* initialState !*/10], !/* retainedProps !*/component[!/* retainedProps !*/11], !/* reducer !*/component[!/* reducer !*/12], !/* jsElementWrapped !*/component[!/* jsElementWrapped !*/13] ]; } exports.component = component; exports.make = make;
  86. @coding_lawyer function App(Props) { var title = Props.title; return React.createElement(

    “div", undefined, React.createElement( "div", { className: “title" }, title), React.createElement(Game.make, { }) ); } var make = App; exports.make = make; new syntax (v3) [@react.component] let make = (~title) !=> <div> <div className=“title"> {React.string(title)} !</div> <Game !/> !</div>;
  87. @coding_lawyer const App = (Props) !=> ( <div> <div className="title">

    {React.string(Props.title)} !</div> <Game !/> !</div>; ) var make = App; exports.make = make; new syntax (v3) [@react.component] let make = (~title) !=> <div> <div className=“title"> {React.string(title)} !</div> <Game !/> !</div>;
  88. @coding_lawyer var component = ReasonReact.statelessComponent("App"); function make(title, _children) { return

    !/* record !*/[ !/* debugName !*/component[!/* debugName !*/0], !/* reactClassInternal !*/component[!/* reactClassInternal !*/1], !/* handedOffState !*/component[!/* handedOffState !*/2], !/* willReceiveProps !*/component[!/* willReceiveProps !*/3], !/* didMount !*/component[!/* didMount !*/4], !/* didUpdate !*/component[!/* didUpdate !*/5], !/* willUnmount !*/component[!/* willUnmount !*/6], !/* willUpdate !*/component[!/* willUpdate !*/7], !/* shouldUpdate !*/component[!/* shouldUpdate !*/8], !/* render !*/(function (_self) { return React.createElement( “div", undefined, React.createElement( "div", { className: “title" }, title), React.createElement(Game.make, { }) ); }), !/* initialState !*/component[!/* initialState !*/10], !/* retainedProps !*/component[!/* retainedProps !*/11], !/* reducer !*/component[!/* reducer !*/12], !/* jsElementWrapped !*/component[!/* jsElementWrapped !*/13] ]; } exports.component = component; exports.make = make; const App = (Props) !=> ( <div> <div className="title"> {React.string(Props.title)} !</div> <Game !/> !</div>; ) var make = App; exports.make = make; new syntax (v3) old syntax (v2)
  89. @coding_lawyer type system

  90. @coding_lawyer clearer and safer code

  91. @coding_lawyer superior to Flow and TypeScript

  92. @coding_lawyer type inference

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

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

    = (a, b) !=> a + b !/* (int, int) !=> int !*/
  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 type field = | Empty | Marked(player); type gameState

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

  101. @coding_lawyer pattern matching

  102. @coding_lawyer Game Board App BoardRow Square

  103. @coding_lawyer React.useReducer( (state: state, action: action) !=> switch (action) {

    | Restart !=> initialState | ClickSquare((id: string)) !=> let updatedBoard = updateBoard( state.board, state.gameState, id); let updatedGs = checkGameState3x3( updatedBoard, state.board, state.gameState); { board: updatedBoard, gameState: updatedGs, };}, …);
  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: gameState, value: field) { | (Playing(_), Marked(_)) => value | (Playing(player), Empty) => Marked(player) | (_, _) => Empty } : value ) );
  105. @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: gameState, value: field) { | (Playing(_), Marked(_)) => value | (Playing(player), Empty) => Marked(player) | (_, _) => Empty } : value ) );
  106. @coding_lawyer type field = | Empty | Marked(player); type gameState

    = | Playing(player) | Winner(player) | Draw;
  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 /* determines the value of the clicked square */

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

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

    (Cross, _, _) => Winner(Cross) | (Circle, _, _) => Winner(Circle) | (_, true, []) => Draw | (_, false, []) => whosPlaying(gameState) | _ => check(tail) };
  117. @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); } }
  118. @coding_lawyer Why should you use React in Reason?

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

  120. @coding_lawyer strong type system

  121. @coding_lawyer pattern matching

  122. @coding_lawyer functional programming features

  123. @coding_lawyer JavaScript-like syntax React friendly

  124. @coding_lawyer Learn ReasonML! learnReasonML.com

  125. @coding_lawyer 
 codinglawyer.io @coding_lawyer

  126. @coding_lawyer Thank You

  127. @coding_lawyer codinglawyer.io @coding_lawyer learnReasonML.com