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
Mateusz Zatorski
September 13, 2018
Technology
2
400
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
41
React Router 1.0
knowbody
1
93
Other Decks in Technology
See All in Technology
Perl歴約10年のエンジニアがフルスタックTypeScriptに出会ってみた
papix
1
210
От ручной разметки к LLM: как мы создавали облако тегов в Lamoda. Анастасия Ангелова, Data Scientist, Lamoda Tech
lamodatech
0
830
CodePipelineのアクション統合から学ぶAWS CDKの抽象化技術 / codepipeline-actions-cdk-abstraction
gotok365
5
320
OPENLOGI Company Profile for engineer
hr01
1
24k
白金鉱業Meetup_Vol.18_AIエージェント時代のUI/UX設計
brainpadpr
1
240
Linuxのパッケージ管理とアップデート基礎知識
go_nishimoto
0
680
Classmethod AI Talks(CATs) #21 司会進行スライド(2025.04.17) / classmethod-ai-talks-aka-cats_moderator-slides_vol21_2025-04-17
shinyaa31
0
630
ここはMCPの夜明けまえ
nwiizo
32
12k
AWSの新機能検証をやる時こそ、Amazon Qでプロンプトエンジニアリングを駆使しよう
duelist2020jp
1
290
Dynamic Reteaming And Self Organization
miholovesq
3
680
AWSのマルチアカウント管理 ベストプラクティス最新版 2025 / Multi-Account management on AWS best practice 2025
ohmura
4
350
SREからゼロイチプロダクト開発へ ー越境する打席の立ち方と期待への応え方ー / Product Engineering Night #8
itkq
2
1.1k
Featured
See All Featured
Large-scale JavaScript Application Architecture
addyosmani
512
110k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
160
15k
YesSQL, Process and Tooling at Scale
rocio
172
14k
Thoughts on Productivity
jonyablonski
69
4.6k
How to Think Like a Performance Engineer
csswizardry
23
1.5k
Docker and Python
trallard
44
3.4k
Gamification - CAS2011
davidbonilla
81
5.2k
Why Our Code Smells
bkeepers
PRO
336
57k
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
Writing Fast Ruby
sferik
628
61k
Product Roadmaps are Hard
iamctodd
PRO
52
11k
GraphQLとの向き合い方2022年版
quramy
46
14k
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>;