Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Building mobile apps in React Native using Reas...
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Mateusz Zatorski
September 13, 2018
Technology
2
470
Building mobile apps in React Native using ReasonML
These are my slides from the LambdUp 2018 conference in Prague.
https://www.lambdup.io/
Mateusz Zatorski
September 13, 2018
Tweet
Share
More Decks by Mateusz Zatorski
See All by Mateusz Zatorski
The missing R in React
knowbody
0
45
React Router 1.0
knowbody
1
99
Other Decks in Technology
See All in Technology
ガバメントクラウドにおけるAWSの長期継続割引について
takeda_h
2
190
Claude Code のコード品質がばらつくので AI に品質保証させる仕組みを作った話 / A story about building a mechanism to have AI ensure quality, because the code quality from Claude Code was inconsistent
nrslib
13
8k
Google系サービスで文字起こしから勝手にカレンダーを埋めるエージェントを作った話
risatube
0
180
It’s “Time” to use Temporal
sajikix
1
160
楽しく学ぼう!ネットワーク入門
shotashiratori
1
380
Yahoo!ショッピングのレコメンデーション・システムにおけるML実践の一例
lycorptech_jp
PRO
1
210
JAWS DAYS 2026 楽しく学ぼう!ストレージ 入門
yoshiki0705
2
190
20260311 ビジネスSWG活動報告(デジタルアイデンティティ人材育成推進WG Ph2 活動報告会)
oidfj
0
330
AWS DevOps Agent vs SRE俺 / AWS DevOps Agent vs me, the SRE
sms_tech
3
830
最強のAIエージェントを諦めたら品質が上がった話 / how quality improved after giving up on the strongest AI agent
kt2mikan
0
190
身体を持ったパーソナルAIエージェントの 可能性を探る開発
yokomachi
1
120
モブプログラミング再入門 ー 基本から見直す、AI時代のチーム開発の選択肢 ー / A Re-introduction of Mob Programming
takaking22
5
1.5k
Featured
See All Featured
The Impact of AI in SEO - AI Overviews June 2024 Edition
aleyda
5
770
SERP Conf. Vienna - Web Accessibility: Optimizing for Inclusivity and SEO
sarafernandez
1
1.3k
We Have a Design System, Now What?
morganepeng
55
8k
Max Prin - Stacking Signals: How International SEO Comes Together (And Falls Apart)
techseoconnect
PRO
0
120
Between Models and Reality
mayunak
2
230
So, you think you're a good person
axbom
PRO
2
2k
Groundhog Day: Seeking Process in Gaming for Health
codingconduct
0
120
Automating Front-end Workflow
addyosmani
1370
200k
Faster Mobile Websites
deanohume
310
31k
Being A Developer After 40
akosma
91
590k
Applied NLP in the Age of Generative AI
inesmontani
PRO
4
2.2k
Jess Joyce - The Pitfalls of Following Frameworks
techseoconnect
PRO
1
110
Transcript
Building mobile apps in React Na4ve using ReasonML
Mateusz Zatorski Twi>er: @matzatorski GitHub: @knowbody
Story
Story Introduc4on to ReasonML
Story Introduc4on to ReasonML DEMO
Story Introduc4on to ReasonML DEMO
Why OCaml?
- func0onal - established language - compiled to: bytecode, fast
na0ve or JavaScript - full-featured type system Why OCaml?
OCaml compiler OCaml syntax OCaml seman0cs Bytecode Na0ve
js_of_ocaml OCaml syntax OCaml seman0cs Bytecode Na0ve js_of_ocaml
Bloomberg
OCaml syntax OCaml seman0cs Bytecode Na0ve Compiler backend replaced by
BuckleScript OCaml syntax OCaml seman0cs BuckleScript
Facebook
What is ReasonML?
Compiler frontend replaced by Reason Reason syntax OCaml seman0cs Bytecode
Na0ve
Combining everything together Reason syntax OCaml seman0cs BuckleScript
Where we are today? - syntax familiar to JS developers
- full power of OCaml - clean and readable JS output
Reason CLI
Reason CLI global binaries needed by editor plugins Comes with
a few extra tools: - refmt - “Reason format” - PreOer was inspired by refmt - merlin - engine powering type hint, refactor, real-0me errors, jump to defini0ons, etc. to our editors. - REPL - called rtop, interac0vely evaluates code - re:bench - online benchmarking playground - Redex - the Reason packages registry - ocamlc, ocamlopt, ocamlrun - bare ocaml compilers
Data types
Strings “Hello world” Characters ‘a’ Integers 27 -13 Floats 27.0
-13.0 Integer addi4on 27 + 13 Float addi4on 27.0 +. 13.0 Integer division/mul4plica4on 14 / 2 * 8 Float division/mul4plica4on 14.0 /. 2.0 *. 8.0 Float exponen4a4on 3.0 ** 3.0 String concatena4on “Hello ” ++ “world”
Comparison > < >= <= Boolean opera4ons ! && ||
Reference, physical (deep) equality === == Immutable lists [3, 2, 1] Arrays [|1, 2, 3|] Records type person = {age: int}; {age: 18} Comments /* my comment */
Tuple type let coordinates: (float, float) = (48.0, -120.0); let
xCoordinate = getX(coordinates); let yCoordinate = getY(coordinates);
Record type access the individual fields in a record using
the . operator: type person = { name: string, age: int, }; let matt = {name: "Mateusz", age: 12}; matt.name; /* "Mateusz" */ matt.age; /* 12 */
Variant type Variant as set of symbols (enum) type shoesColor
= | Red | Blue | Green | Black; Variant as data structure type point = | Point(float, float); type shape = | Rectangle(point, point) | Circle(point, float);
Variant type Variant as self-recursive data structure type intTree =
| Empty /* atomic */ | Node(int, intTree, intTree); /* compound */
Polymorphic type type list('a) = | Nil | Cons('a, list(‘a));
let myList = Cons("foo", Cons("bar", Cons("baz", Nil))); Singly-linked list “foo” “bar” “baz” Nil
Op0on type type option('a) = | None | Some('a); let
division = (a: int, b: int) : option(int) => if (b === 0) { None; } else { Some(a / b); }; let myLuckyNumber = division(23, 45);
Expressions
let let hardMath = { let x = 4; let
y = x - 1; x + y }; x and y are not accessible outside of hardMath scope let rec factorial = n => if (n === 0) { 1; } else { n * factorial(n - 1); };
if-else let min = (x, y) => if (x <
y) { x; } else { y; };
PaXern matching
if-else let min = (x, y) => if (x <
y) { x; } else { y; }; let min = (x, y) => switch(x < y) { | true => x | false => y };
Func0ons
Labelled arguments let add = (~x, ~y) => {/* use
x and y here */}; add(~y=5, ~x=6);
Currying let add = (x, y) => x + y;
let inc = add(1); inc(10); /* 11 */ let add = (a, b) => a + b; let alsoAdd = a => b => a + b;
Recursive func0ons let rec factorial = n => if (n
=== 0) { 1; } else { n * factorial(n - 1); };
Modules
Modules module Calc = { let add = (x, y)
=> x + y; }; Calc.add(4, 5);
JavaScript interop
JavaScript interop let jsCalculate: (array(int), int) => int = [%bs.raw
{| function (numbers, scaleFactor) { var result = 0; numbers.forEach(number => { result += number; }); return result * scaleFactor; } |} ]; let calculate = (numbers, scaleFactor) => jsCalculate(Array.of_list(numbers), scaleFactor); Js.log(calculate([1, 2, 3], 10)); /* -> 60 */
Component
Component let component = ReasonReact.statelessComponent("App"); let make = _children =>
{ ...component, render: _self => <div> <h1> (ReasonReact.string("Welcome!")) </h1> </div>, };
Component let component = ReasonReact.statelessComponent(“App"); let make = (~message, _children)
=> { ...component, render: _self => <div> (ReasonReact.string(message)) </div>, };
Component let component = ReasonReact.statelessComponent("App"); let make = (~fooProp, ~barProp,
_children) => { ...component, /* render and lifecycle methods go here */ };
Stateful component
type state = {isEnabled: bool}; type action = | Click;
let component = ReasonReact.reducerComponent("App"); let make = _children => { ...component, initialState: () => {isEnabled: true}, reducer: (action, state) => switch (action) { | Click => ReasonReact.Update({isEnabled: ! state.isEnabled}) }, render: self => <div> <h1 onClick=(_event => self.send(Click))> (ReasonReact.string(self.state.isEnabled ? "on" : "off")) </h1> </div>, };
type state = {isEnabled: bool}; type action = | Click;
let component = ReasonReact.reducerComponent("App"); let make = _children => { ...component, initialState: () => {isEnabled: true}, reducer: (action, state) => switch (action) { | Click => ReasonReact.Update({isEnabled: ! state.isEnabled}) }, render: self => <div> <h1 onClick=(_event => self.send(Click))> (ReasonReact.string(self.state.isEnabled ? "on" : "off")) </h1> </div>, };
type state = {isEnabled: bool}; type action = | Click;
let component = ReasonReact.reducerComponent("App"); let make = _children => { ...component, initialState: () => {isEnabled: true}, reducer: (action, state) => switch (action) { | Click => ReasonReact.Update({isEnabled: ! state.isEnabled}) }, render: self => <div> <h1 onClick=(_event => self.send(Click))> (ReasonReact.string(self.state.isEnabled ? "on" : "off")) </h1> </div>, };
type state = {isEnabled: bool}; type action = | Click;
let component = ReasonReact.reducerComponent("App"); let make = _children => { ...component, initialState: () => {isEnabled: true}, reducer: (action, state) => switch (action) { | Click => ReasonReact.Update({isEnabled: ! state.isEnabled}) }, render: self => <div> <h1 onClick=(_event => self.send(Click))> (ReasonReact.string(self.state.isEnabled ? "on" : "off")) </h1> </div>, };
type state = {isEnabled: bool}; type action = | Click;
let component = ReasonReact.reducerComponent("App"); let make = _children => { ...component, initialState: () => {isEnabled: true}, reducer: (action, state) => switch (action) { | Click => ReasonReact.Update({isEnabled: ! state.isEnabled}) }, render: self => <div> <h1 onClick=(_event => self.send(Click))> (ReasonReact.string(self.state.isEnabled ? "on" : "off")) </h1> </div>, };
type state = {isEnabled: bool}; type action = | Click;
let component = ReasonReact.reducerComponent("App"); let make = _children => { ...component, initialState: () => {isEnabled: true}, reducer: (action, state) => switch (action) { | Click => ReasonReact.Update({isEnabled: ! state.isEnabled}) }, render: self => <div> <h1 onClick=(_event => self.send(Click))> (ReasonReact.string(self.state.isEnabled ? "on" : "off")) </h1> </div>, };
type state = {isEnabled: bool}; type action = | Click;
let component = ReasonReact.reducerComponent("App"); let make = _children => { ...component, initialState: () => {isEnabled: true}, reducer: (action, state) => switch (action) { | Click => ReasonReact.Update({isEnabled: ! state.isEnabled}) }, render: self => <div> <h1 onClick=(_event => self.send(Click))> (ReasonReact.string(self.state.isEnabled ? "on" : "off")) </h1> </div>, };
type state = {isEnabled: bool}; type action = | Click;
let component = ReasonReact.reducerComponent("App"); let make = _children => { ...component, initialState: () => {isEnabled: true}, reducer: (action, state) => switch (action) { | Click => ReasonReact.Update({isEnabled: ! state.isEnabled}) }, render: self => <div> <h1 onClick=(_event => self.send(Click))> (ReasonReact.string(self.state.isEnabled ? "on" : "off")) </h1> </div>, };
Arrays
type person = { name: string, age: int, }; let
people: array(person) = [| {name: "Matt", age: 26}, {name: "Czysty", age: 6}, |]; Arrays
type person = { name: string, age: int, }; let
people: array(person) = [| {name: "Matt", age: 26}, {name: "Czysty", age: 6}, |]; let component = ReasonReact.statelessComponent("App"); let make = _children => { ...component, render: _self => <div> ( ReasonReact.array( Array.map( (person: person) => <p> (ReasonReact.string(person.name)) </p>, people, ), ) ) </div>, };
type person = { name: string, age: int, }; let
people: array(person) = [| {name: "Matt", age: 26}, {name: "Czysty", age: 6}, |]; let component = ReasonReact.statelessComponent("App"); let make = _children => { ...component, render: _self => <div> ( people |> Array.map((person: person) => <p> (ReasonReact.string(person.name)) </p> ) |> ReasonReact.array ) </div>, };
Let’s build something
Adding ReasonML to React Na0ve project yarn add bs-platform reason-react
bs-react-native
touch bsconfig.json { "name": "my-reason-react-native-app", "reason": { "react-jsx": 2 },
"bsc-flags": ["-bs-super-errors"], "bs-dependencies": ["bs-react-native", "reason-react"], "sources": [ { "dir": "src" } ], "package-specs": { "module": "commonjs", "in-source": true }, "refmt": 3 } Add bsconfig.json
Modify index.js import { app } from './src/App'; import React
from 'react'; import { AppRegistry } from 'react-native'; AppRegistry.registerComponent('MyReasonApp', () => app);
Let’s add our first component src/App.re open BsReactNative; let styles
= StyleSheet.create( Style.( { "container": style([flex(1.), justifyContent(Center), alignItems(Center)]), "text": style([fontSize(Float(26.))]), } ), ); let app = () => <View style=styles##container> <Text style=styles##text> (ReasonReact.string("Let's get this party started! " ++ {js||js})) </Text> </View>;