Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Write better React (v3 ReasonReact)
Search
David Kopal
May 11, 2019
Technology
690
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Write better React (v3 ReasonReact)
David Kopal
May 11, 2019
More Decks by David Kopal
See All by David Kopal
Use ReasonML in your React applications (RuhrJS 2018)
codinglawyer
2
320
Use Reason in your React applications
codinglawyer
3
620
Unleash the power of the higher-order components
codinglawyer
2
290
Other Decks in Technology
See All in Technology
AI秘書と毎日働くのはもう当たり前。開発以外の業務に足りない機能をどう埋める?
minorun365
PRO
4
1.9k
Agent × Maestro で始める モバイル E2E 端末準備からテスト実行・結果確認まで
sansantech
PRO
0
230
推論基盤と Scale-Up Interconnect の現状と制約から俯瞰する技術動向
markunet
2
550
Claude Code をローカルとサーバー上で利用した際の Bedrock 利用料をユーザー単位で一本化してみる
ohorig
0
180
reInvent2026stby LT00 "Change your life!"
shinichirokawano
1
400
素人でもできた!AIを使った短編小説創作入門
delhi09
PRO
0
140
PostgreSQL at Microsoft: Open Source, AI, & Cloud | Claire Giordano | PGConf.EU 2026
clairegiordano
0
110
生成AI時代、PMは事業責任者に進化するともっと面白い〜PMだからこそ事業構造を動かせる時代に〜
kakehashi
PRO
1
940
AI時代、つくる力を自分たちの手に。 ──電通×KAG、アジャイルとAI駆動開発で挑む開発の変革
yuukiyo
3
410
AI時代のエンジニアの情報発信〜個人の発信を組織の力に変える〜
ryo_kawamata
0
190
Deep Data Security 機能解説
oracle4engineer
PRO
3
950
シンプルな設定ファイルで実現する AWS IAM Identity Center の ユーザー管理Terraformフレームワークを公開しました / Simplifying AWS IAM Identity Center User Management: An Open-Source Terraform Framework
yamaguchitk333
1
330
Featured
See All Featured
What's in a price? How to price your products and services
michaelherold
247
13k
世界の人気アプリ100個を分析して見えたペイウォール設計の心得
akihiro_kokubo
PRO
74
43k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
38
3.1k
エンジニアに許された特別な時間の終わり
watany
109
250k
JAMstack: Web Apps at Ludicrous Speed - All Things Open 2022
reverentgeek
1
650
Skip the Path - Find Your Career Trail
mkilby
1
260
brightonSEO & MeasureFest 2025 - Winning Strategies for Black Friday CRO & PPC - Christian Goodrich
cargoodrich
3
880
[SF Ruby Conf 2025] Rails X
palkan
3
1.5k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
33
5.4k
The Impact of AI in SEO - AI Overviews June 2024 Edition
aleyda
6
1.2k
The World Runs on Bad Software
bkeepers
PRO
72
12k
sira's awesome portfolio website redesign presentation
elsirapls
0
470
Transcript
Write better React with ReasonML David Kopal
@coding_lawyer codinglawyer.io learnReasonML.com I’m David Kopal
@coding_lawyer Who heard about ason?
@coding_lawyer
@coding_lawyer Who wants to write better React?
@coding_lawyer React isn’t a native JavaScript library
@coding_lawyer
@coding_lawyer Immutability
@coding_lawyer Immutability
@coding_lawyer Immutability
@coding_lawyer Immutability Functional programming
@coding_lawyer Immutability Functional programming
@coding_lawyer Immutability Functional programming
@coding_lawyer Immutability Type system Functional programming
@coding_lawyer Immutability Type system Functional programming
@coding_lawyer Immutability Type system Functional programming
@coding_lawyer Immutability Type system Functional programming
@coding_lawyer Immutability Type system Functional programming
@coding_lawyer Immutability Type system Functional programming
@coding_lawyer Immutability Type system Functional programming
@coding_lawyer
@coding_lawyer semantics Javascript-like syntax
@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)) };
@coding_lawyer compiler
@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)) };
@coding_lawyer JavaScript interop
@coding_lawyer
@coding_lawyer Reason is compatible with React
@coding_lawyer Reason is compatible with React React was developed for
Reason
@coding_lawyer adjusted JavaScript to React’s needs
@coding_lawyer
@coding_lawyer
@coding_lawyer
@coding_lawyer
@coding_lawyer
@coding_lawyer
@coding_lawyer
@coding_lawyer
@coding_lawyer semantics Javascript-like syntax
@coding_lawyer safer React
@coding_lawyer “[Reason] is the best way to take React to
the next level” Jordan Walke, creator of Reason, React
@coding_lawyer Tic Tac Toe
@coding_lawyer
@coding_lawyer
@coding_lawyer
@coding_lawyer
@coding_lawyer Game Board App BoardRow Square
@coding_lawyer Game Board App BoardRow Square
@coding_lawyer Game Board App BoardRow Square
@coding_lawyer Game Board App BoardRow Square
@coding_lawyer Game Board App BoardRow Square
@coding_lawyer Game Board App BoardRow Square
@coding_lawyer components
@coding_lawyer stateless component
@coding_lawyer Game Board App BoardRow Square
@coding_lawyer [@react.component] let make = (~title) !=> <div> <div className=“title">
{React.string(title)} !</div> <Game !/> !</div>;
@coding_lawyer [@react.component] let make = (~title) !=> <div> <div className=“title">
{React.string(title)} !</div> <Game !/> !</div>;
@coding_lawyer [@react.component] let make = (~title) !=> <div> <div className=“title">
{React.string(title)} !</div> <Game !/> !</div>;
@coding_lawyer [@react.component] let make = (~title) !=> <div> <div className=“title">
{React.string(title)} !</div> <Game !/> !</div>;
@coding_lawyer stateful component
@coding_lawyer Game Board App BoardRow Square
@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>;};
@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>;};
@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>;};
@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>;};
@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>;};
@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>;};
@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>;};
@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>;};
@coding_lawyer Game Board App BoardRow Square
@coding_lawyer Game Board App BoardRow Square
@coding_lawyer Game Board App BoardRow Square
@coding_lawyer Game Board App BoardRow Square
@coding_lawyer Game Board App BoardRow Square
@coding_lawyer Game Board App BoardRow Square
@coding_lawyer Game Board App BoardRow Square
@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>;};
@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>;};
@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, };}, …);
@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, };}, …);
@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>;};
@coding_lawyer old syntax (v2) vs new syntax (v3)
@coding_lawyer [@react.component] let make = (~title) !=> <div> <div className=“title">
{React.string(title)} !</div> <Game !/> !</div>; new syntax (v3)
@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)
@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;
@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>;
@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>;
@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)
@coding_lawyer type system
@coding_lawyer clearer and safer code
@coding_lawyer superior to Flow and TypeScript
@coding_lawyer type inference
@coding_lawyer !/* type inference by the compiler !*/ let plus
= (a, b) !=> a + b
@coding_lawyer !/* type inference by the compiler !*/ let plus
= (a, b) !=> a + b !/* (int, int) !=> int !*/
@coding_lawyer type field = | Empty | Marked(player); type gameState
= | Playing(player) | Winner(player) | Draw; type player = | Cross | Circle;
@coding_lawyer type field = | Empty | Marked(player); type gameState
= | Playing(player) | Winner(player) | Draw; type player = | Cross | Circle;
@coding_lawyer type field = | Empty | Marked(player); type gameState
= | Playing(player) | Winner(player) | Draw; type player = | Cross | Circle;
@coding_lawyer type field = | Empty | Marked(player); type gameState
= | Playing(player) | Winner(player) | Draw; type player = | Cross | Circle;
@coding_lawyer type field = | Empty | Marked(player); type gameState
= | Playing(player) | Winner(player) | Draw; type player = | Cross | Circle;
@coding_lawyer
@coding_lawyer pattern matching
@coding_lawyer Game Board App BoardRow Square
@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, };}, …);
@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 ) );
@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 ) );
@coding_lawyer type field = | Empty | Marked(player); type gameState
= | Playing(player) | Winner(player) | Draw;
@coding_lawyer /* determines the value of the clicked square */
switch (gameState: gameState, value: field) { | (Playing(_), Marked(_)) => value | (Playing(player), Empty) => Marked(player) | (_, _) => Empty }
@coding_lawyer /* determines the value of the clicked square */
switch (gameState: gameState, value: field) { | (Playing(_), Marked(_)) => value | (Playing(player), Empty) => Marked(player) | (_, _) => Empty }
@coding_lawyer /* determines the value of the clicked square */
switch (gameState: gameState, value: field) { | (Playing(_), Marked(_)) => value | (Playing(player), Empty) => Marked(player) | (_, _) => Empty }
@coding_lawyer /* determines the value of the clicked square */
switch (gameState: gameState, value: field) { | (Playing(_), Marked(_)) => value | (Playing(player), Empty) => Marked(player) | (_, _) => Empty }
@coding_lawyer /* determines the value of the clicked square */
switch (gameState: gameState, value: field) { | (Playing(_), Marked(_)) => value | (Playing(player), Empty) => Marked(player) | (_, _) => Empty }
@coding_lawyer /* determines the value of the clicked square */
switch (gameState: gameState, value: field) { | (Playing(_), Marked(_)) => value | (Playing(player), Empty) => Marked(player) | (_, _) => Empty }
@coding_lawyer /* determines the value of the clicked square */
switch (gameState: gameState, value: field) { | (Playing(_), Marked(_)) => value | (Playing(player), Empty) => Marked(player) | (_, _) => Empty }
@coding_lawyer /* determines the value of the clicked square */
switch (gameState: gameState, value: field) { | (Playing(_), Marked(_)) => value | (Playing(player), Empty) => Marked(player) /* | (_, _) => Empty */ }
@coding_lawyer
@coding_lawyer switch ( getWinner(flattenBoard, head), gameEnded(flattenBoard), tail, ) { |
(Cross, _, _) => Winner(Cross) | (Circle, _, _) => Winner(Circle) | (_, true, []) => Draw | (_, false, []) => whosPlaying(gameState) | _ => check(tail) };
@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); } }
@coding_lawyer Why should you use React in Reason?
@coding_lawyer Reason is compatible with React's principles
@coding_lawyer strong type system
@coding_lawyer pattern matching
@coding_lawyer functional programming features
@coding_lawyer JavaScript-like syntax React friendly
@coding_lawyer Learn ReasonML! learnReasonML.com
@coding_lawyer codinglawyer.io @coding_lawyer
@coding_lawyer Thank You
@coding_lawyer codinglawyer.io @coding_lawyer learnReasonML.com