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
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Des apps multiplateformes avec reason-react-native
Search
Mathieu Acthernoene
May 21, 2019
Technology
100
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Des apps multiplateformes avec reason-react-native
Mathieu Acthernoene
May 21, 2019
More Decks by Mathieu Acthernoene
See All by Mathieu Acthernoene
Advanced TypeScript: How we made our router typesafe
zoontek
3
1.5k
Designing and maintaining an open-source React Native library
zoontek
0
140
Manage microservices like a Chef
zoontek
0
1.3k
Other Decks in Technology
See All in Technology
Bet AI Day 2026丨Production-Ready AI Agents — エンタープライズの実務を任せるための設計と運用
layerx
PRO
4
2.6k
AI時代だからこそ、スケールしないことをやろう
yutashigemura
1
110
SQL文一行も書けない人事がCortexもろもろを使って人事業務を楽にしてみる
ponponmikankan
1
170
AI活用の現在地、 ちゃんと見えてますか?/XPfest-2026
visional_engineering_and_design
0
170
2026/09/10 Spring_Bootから_Jakarta_EE_MicroProfileへの移行
megascus
0
250
スクラムで身についていた動き方を、XPで捉え直してみた
codmoninc
PRO
1
320
AI時代のAPI品質を支えるガードレール / API Guardrails for API quality in the AI era
yokawasa
1
180
[DroidKaigi 2026] Making UI specifications visible: Android UI development in the AI agent era supported by Compose Screenshot Testing and galleries
syarihu
0
610
Amazon S3 Tablesに全部任せてみた結果——コンパクション/スナップショット管理は本当に手放せるか
shigeruoda
0
420
Screen Lens - 今見てる画面を翻訳する
komagata
0
140
Code4Lib JAPANカンファレンス2026 開会挨拶 / Code4Lib JAPAN Conference 2026: Opening Remarks
ykiyota
0
250
20260906 「AWS運用入門」著者が教える、運用業務への生成AI活用入門
masaruogura
0
250
Featured
See All Featured
Lightning Talk: Beautiful Slides for Beginners
inesmontani
PRO
2
680
It's Worth the Effort
3n
188
29k
GitHub's CSS Performance
jonrohan
1033
470k
Making Projects Easy
brettharned
120
6.7k
Raft: Consensus for Rubyists
vanstee
141
7.7k
StorybookのUI Testing Handbookを読んだ
zakiyama
31
6.9k
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
1
380
GraphQLとの向き合い方2022年版
quramy
50
15k
Reality Check: Gamification 10 Years Later
codingconduct
0
2.3k
Designing for humans not robots
tammielis
254
26k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.6k
Accessibility Awareness
sabderemane
1
200
Transcript
! 1 Multi-platforms apps with reason-react-native
! 2 Mathieu Acthernoene @zoontek
! 3 ⏱ Disclaimer 30 min is short I will
be brief on non-primary points
! 4 React Native A mobile framework to build user
interfaces Supported platforms : iOS, Android & UWP
! 5 React Native <View /> Credit : Formidable labs
UIView android.view.View
! 6 ReasonML Alternate syntax + tooling for OCaml Looks
like modern JavaScript
! 7 let a = 1; /* int */ let
b = 1.0; /* float */ let c = "Hello"; /* string */ let d = 'Z'; /* char */ let e = true; /* boolean */ let f = [1, 2, 3]; /* list(int) */ let g = [|1, 2, 3|]; /* array(int) */ let h = Some(x); /* option('a) */ let i = (); /* unit */ ReasonML
! 8 type user = { name: string, age: int,
}; let me = { name: “Matthieu", age: 27, }; let meLater = { ...me, age: 28, }; ReasonML
! 9 ReasonML let sayHi = name X> Js.log("Hi "
Z[ name Z[ “!”); let add = (a, b) X> a +. b;
! 10 BuckleScript OCaml to ES5 JS compiler Supports both
syntaxes
! 11 UIView android.view.View compile time runtime time
! 12 $ Let’s create a project
! 13
! 14 Highly complex backend A Google Cloud Function which
run Puppeteer every hour (with Cloud Scheduler) and store a JSON file
! 15 { "dates": [ "2019-05-19", "2019-05-20", // … ],
"pools": [ { "id": "alfred-nakache", "name": "Alfred Nakache", "coordinates": { "latitude": 48.871687, "longitude": 2.378887 }, "hours": [ [["08:00", "18:00"]], [], [["07:00", "08:30"], ["11:30", "13:30"], ["16:30", "18:00"]] // … Backend
! 16 $ brew install node yarn watchman $ yarn
global add react-native-cli reason-cli@latest-macos Things you should install — or —
! 17 $ react-native init ParisPiscine && cd ParisPiscine
! 18 $ yarn add --dev bs-platform $ yarn add
reason-react $ yarn add git://github.com/reasonml-community/bs- react-native#756f2f34fefeed1c3d1ed389330278ecd0434aca $ yarn add bs-fetch @glennsl/bs-json # extras $ touch bsconfig.json
! 19 // bsconfig.json { "name": "paris-piscine", "version": "0.1.0", "suffix":
".bs.js", "refmt": 3, "warnings": { "error": "+101" }, "reason": { "react-jsx": 3 }, "bs-dependencies": [ "@glennsl/bs-json", "bs-fetch", "reason-react", "bs-react-native-monorepo/reason-react-native" ], // …
! 20 // …bsconfig.json "package-specs": { "module": "es6", "in-source": true
}, "sources": { "dir": "src", "subdirs": true }, "js-post-build": { "cmd": "./node_modules/bs-react-native-monorepo/ git-monorepo-usage-trick" } }
! 21 // package.json { "name": "paris-piscine", "version": "0.0.1", "scripts":
{ "bs:clean": "bsb -clean-world", "bs:start": "bsb -make-world -w", "bs:build": "bsb -make-world", "rn:start": "node node_modules/react-native/ local-cli/cli.js start" }, // …
! 22 $ rm -rf .buckconfig .flowconfig __tests__ App.js $
mkdir src && touch src/App.re A bit of cleanup
! 23 // src/App.re open ReactNative; let styles = StyleSheet.create(
Style.{ "container": style(~flex=1., ~alignItems=`center, ~justifyContent=`center, ()), "text": style(~fontSize=24., ()), }, );
! 24 // …src/App.re [@react.component] let make = () X>
{ <View style=styles##container> <Text style=styles##text> "Hello LilleFP”u>React.string </Text> </View>; };
! 25 // src/App.bs.js // Generated by BUCKLESCRIPT VERSION 5.0.3
import * as React from "react"; import * as ReactNative from "react-native"; var styles = ReactNative.StyleSheet.create({ container: { alignItems: “center”, flex: 1, justifyContent: “center”, }, text: { fontSize: 24 }, });
! 26 // …src/App.bs.js function App(Props) { return React.createElement(ReactNative.View, {
style: styles.container, children: React.createElement(ReactNative.Text, { style: styles.text, children: "Hello LilleFP", }), }); } var make = App; export { styles, make };
! 27 // index.js import { AppRegistry } from "react-native";
import { make as App } from "./src/App.bs.js"; import { name as appName } from "./app.json"; AppRegistry.registerComponent(appName, () X> App);
! 28
! 29
! 30 // Pools.re let url = "http://localhost:8080"; type coordinates
= { latitude: float, longitude: float, }; type pool = {coordinates}; type fetchedData = { dates: array(string), pools: array(pool), }; Fetching & decoding data
! 31 // …Pools.re module Decode = { open Json.Decode;
let coordinates = json X> { latitude: field("latitude", float, json), longitude: field("longitude", float, json), }; let pool = json X> {coordinates: field("coordinates", coordinates, json)}; let fetchedData = json X> { dates: field("dates", array(string), json), pools: field("pools", array(pool), json), }; }; Fetching & decoding data
! 32 // …Pools.re let fetchData = () X> Js.Promise.(
Fetch.fetch(url) yz then_(Fetch.Response.json) yz then_(json X> Decode.fetchedData(json)u>resolve) ); Fetching & decoding data
! 33 // App.re open ReactNative; open Belt; type state
= | Loading | Error | Loaded(Pools.fetchedData); type action = | FetchData | ReceiveError | ReceiveData(Pools.fetchedData); Displaying data
! 34 // …App.re let styles = StyleSheet.create( Style.{ "container":
style(~flex=1.,~alignItems=`center, ~justifyContent=`center, ()), }, ); Displaying data
! 35 // …App.re [@react.component] let make = () X>
{ let (state, dispatch) = React.useReducer( (state, action) X> switch (action) { | FetchData X> Loading | ReceiveError X> Error | ReceiveData(data) X> Loaded(data) }, Loading, ); Displaying data
! 36 // …App.re [@react.component] let make = () X>
{ // … let displayFetchingError = () X> Alert.alert( ~title={js|Une erreur est survenue|js}, ~message={js|Impossible d'accéder aux données|js}, (), ); Displaying data
! 37 React.useEffect1(() X> { Js.Promise.( Pools.fetchData() yz then_((data: Pools.fetchedData)
X> dispatch(ReceiveData(data))u>resolve ) yz catch(_error X> { displayFetchingError(); dispatch(ReceiveError)u>resolve; }) yz ignore ); None; }, [||]); Displaying data
! 38 <View style=styles##container> {switch (state) { | Loading X>
<ActivityIndicator size=ActivityIndicator.Size.large /> | Error X> React.null | Loaded(data) X> switch (data.pools[0]) { | Some(pool) X> <Text> {("First pool: " Z[ pool.name)u>React.string} </Text> | None X> <Text> "No pool found"u>React.string </Text> } }} </View> Displaying data
! 39 All of this is cool, yeah But how
do I use existing libs ?
! 40 $ yarn add react-navigation react-native-gesture-handler react-native-maps $ react-native
link react-native-gesture-handler $ react-native link react-native-maps Let’s add some deps
! 41 // src/vendor/ReactNavigation.re type stackNavigatorConfig; type navigationProp('routeParams, 'pushedParams) =
{ . [@bs.meth] "push": (string, 'pushedParams) X> unit, [@bs.meth] "goBack": unit X> unit, "state": { . "key": string, "routeName": string, "params": 'routeParams, }, }; Binding example n°1 (react-navigation)
! 42 // …src/vendor/ReactNavigation.re [@bs.obj] external stackNavigatorConfig: (~headerMode: [@bs.string] [
| `float | `screen | `none]=?, unit) X> stackNavigatorConfig = ""; [@bs.module "react-navigation"] external createStackNavigator: (Js.t('a), stackNavigatorConfig) X> React.element = ""; [@bs.module "react-navigation"] external createAppContainer: React.element X> React.element = ""; Binding example n°1 (react-navigation)
! 43 // src/vendor/MapView.re open ReactNative; include NativeElement; type region;
[@bs.obj] external region: ( ~latitude: float, ~longitude: float, ~latitudeDelta: float, ~longitudeDelta: float ) X> region = ""; Binding example n°2 (react-native-maps)
! 44 // …src/vendor/MapView.re [@react.component] [@bs.module "react-native-maps"] external make: (
~ref: ref=?, ~style: Style.t=?, ~region: region=?, ~children: React.element=? ) X> React.element = "default"; Binding example n°2 (react-native-maps)
! 45 & Diving in the full codebase
! 46 Thank you ! Questions ?