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

Write better React (v3 ReasonReact)

Write better React (v3 ReasonReact)

David Kopal

May 11, 2019
Tweet

More Decks by David Kopal

Other Decks in Technology

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