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
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.4k
Designing and maintaining an open-source React Native library
zoontek
0
130
Manage microservices like a Chef
zoontek
0
1.3k
Other Decks in Technology
See All in Technology
LLMを「主役」にしないための 3つの原則
techtekt
PRO
0
120
そのPoC、何を検証したつもりでしたか? AIプロダクトの価値検証で陥った落とし穴
techtekt
PRO
0
150
個人最適 から 全体最適 へ AI情報共有会・AIギルド・AI-DLC で進める カンリーの組織展開
rfdnxbro
0
1.7k
LLMと共に進化するプロセスを目指して
ymatsuwitter
12
3.3k
PHP と TypeScript の型システム比較:AI 時代の「型」は誰のためにあるのか? #frontend_phpcon_do / frontend_phpcon_do_2026
shogogg
1
250
Oracle Cloud Infrastructure IaaS 新機能アップデート 2026/3 - 2026/5
oracle4engineer
PRO
1
200
Platform Engineering as a Product: Criteria for Improvement and Multi-Tenant Design
kumorn5s
0
510
Agentic Web
dynamis
1
140
探して_入れて_作って_使う_Agent_Skills___LT.pdf
peintangos
2
160
Oracle AI Database@Azure:サービス概要のご紹介
oracle4engineer
PRO
6
1.9k
正解のないAIプロダクトをどう導くか?dodaが挑む、ユーザーの『本音』を構造化する評価設計と検証のリアル
techtekt
PRO
0
190
チームで実践する AI-DLC 思考の軌跡を残すチェックポイント設計
belongadmin
0
2.8k
Featured
See All Featured
Raft: Consensus for Rubyists
vanstee
141
7.5k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
34
2.8k
AI in Enterprises - Java and Open Source to the Rescue
ivargrimstad
0
1.3k
Color Theory Basics | Prateek | Gurzu
gurzu
0
350
Reflections from 52 weeks, 52 projects
jeffersonlam
356
21k
State of Search Keynote: SEO is Dead Long Live SEO
ryanjones
0
200
Measuring Dark Social's Impact On Conversion and Attribution
stephenakadiri
2
210
Utilizing Notion as your number one productivity tool
mfonobong
4
320
My Coaching Mixtape
mlcsv
0
140
ラッコキーワード サービス紹介資料
rakko
1
3.6M
Reality Check: Gamification 10 Years Later
codingconduct
0
2.2k
Site-Speed That Sticks
csswizardry
13
1.2k
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 ?