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
480
2
Share
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
More Decks by Mateusz Zatorski
See All by Mateusz Zatorski
The missing R in React
knowbody
0
46
React Router 1.0
knowbody
1
100
Other Decks in Technology
See All in Technology
脅威をエンジニアリングの糧にして:恐怖を乗り越えた先にあったもの / Turn threats into fuel for engineering: what lay beyond overcoming fear
nrslib
1
360
JEP 522 Deep Dive - G1 GC同期コスト削減によるスループット向上を徹底検証&解説
tabatad
1
520
Generative UI × A2UI で AI エージェントを作った話 AI-DLC も使ってみた!
kmiya84377
1
300
A Harness for Behaviour: how to get AI to generate code that does what we intend, or "TDD in the age of AI"
xpmatteo
1
530
long-running-tasks
cipepser
2
450
最低限これだけ押さえれ大丈夫_Claude Enterprise/Team企業展開ガバナンス入門
tkikuchi
1
590
Oracle AI Database@Google Cloud:サービス概要のご紹介
oracle4engineer
PRO
6
1.5k
Dynamic Workersについて
yusukebe
2
550
AI時代から振り返るTerraform drift運用の歴史 / AI Age Reflections on the History of Terraform Drift Operations
aeonpeople
2
630
Javaで学ぶSOLID原則
negima
1
250
AI駆動開発でなんでもハンズオン環境をつくってみた
yoshimi0227
0
190
Datadog 認定試験の概要と対策
uechishingo
0
210
Featured
See All Featured
Future Trends and Review - Lecture 12 - Web Technologies (1019888BNR)
signer
PRO
0
3.6k
How To Speak Unicorn (iThemes Webinar)
marktimemedia
1
470
Reality Check: Gamification 10 Years Later
codingconduct
0
2.2k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
Unlocking the hidden potential of vector embeddings in international SEO
frankvandijk
0
830
Navigating the Design Leadership Dip - Product Design Week Design Leaders+ Conference 2024
apolaine
1
330
Intergalactic Javascript Robots from Outer Space
tanoku
273
27k
Design of three-dimensional binary manipulators for pick-and-place task avoiding obstacles (IECON2024)
konakalab
0
440
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
231
23k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
12
1.2k
How to Align SEO within the Product Triangle To Get Buy-In & Support - #RIMC
aleyda
2
1.5k
Paper Plane (Part 1)
katiecoart
PRO
0
8.1k
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>;