Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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. @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)) };
  2. @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)) };
  3. @coding_lawyer “[Reason] is the best way to take React to

    the next level” Jordan Walke, creator of Reason, React
  4. @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>;};
  5. @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>;};
  6. @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>;};
  7. @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>;};
  8. @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>;};
  9. @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>;};
  10. @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>;};
  11. @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>;};
  12. @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>;};
  13. @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>;};
  14. @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, };}, …);
  15. @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, };}, …);
  16. @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>;};
  17. @coding_lawyer [@react.component] let make = (~title) !=> <div> <div className=“title">

    {React.string(title)} !</div> <Game !/> !</div>; new syntax (v3)
  18. @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)
  19. @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;
  20. @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>;
  21. @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>;
  22. @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)
  23. @coding_lawyer !/* type inference by the compiler !*/ let plus

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

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

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

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

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

    = | Playing(player) | Winner(player) | Draw; type player = | Cross | Circle;
  29. @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, };}, …);
  30. @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 ) );
  31. @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 ) );
  32. @coding_lawyer type field = | Empty | Marked(player); type gameState

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

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

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

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

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

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

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

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

    switch (gameState: gameState, value: field) { | (Playing(_), Marked(_)) => value | (Playing(player), Empty) => Marked(player) /* | (_, _) => Empty */ }
  41. @coding_lawyer switch ( getWinner(flattenBoard, head), gameEnded(flattenBoard), tail, ) { |

    (Cross, _, _) => Winner(Cross) | (Circle, _, _) => Winner(Circle) | (_, true, []) => Draw | (_, false, []) => whosPlaying(gameState) | _ => check(tail) };
  42. @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); } }