Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Building mobile apps in React Native using Reas...

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

Building mobile apps in React Native using ReasonML

These are my slides from the LambdUp 2018 conference in Prague. https://www.lambdup.io/

Avatar for Mateusz Zatorski

Mateusz Zatorski

September 13, 2018
Tweet

More Decks by Mateusz Zatorski

Other Decks in Technology

Transcript

  1. - func0onal - established language - compiled to: bytecode, fast

    na0ve or JavaScript - full-featured type system Why OCaml?
  2. OCaml syntax OCaml seman0cs Bytecode Na0ve Compiler backend replaced by

    BuckleScript OCaml syntax OCaml seman0cs BuckleScript
  3. Where we are today? - syntax familiar to JS developers

    - full power of OCaml - clean and readable JS output
  4. 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
  5. 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”
  6. 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 */
  7. Tuple type let coordinates: (float, float) = (48.0, -120.0); let

    xCoordinate = getX(coordinates); let yCoordinate = getY(coordinates);
  8. 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 */
  9. 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);
  10. Variant type Variant as self-recursive data structure type intTree =

    | Empty /* atomic */ | Node(int, intTree, intTree); /* compound */
  11. 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
  12. 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);
  13. 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); };
  14. if-else let min = (x, y) => if (x <

    y) { x; } else { y; };
  15. if-else let min = (x, y) => if (x <

    y) { x; } else { y; }; let min = (x, y) => switch(x < y) { | true => x | false => y };
  16. Labelled arguments let add = (~x, ~y) => {/* use

    x and y here */}; add(~y=5, ~x=6);
  17. 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;
  18. Recursive func0ons let rec factorial = n => if (n

    === 0) { 1; } else { n * factorial(n - 1); };
  19. Modules module Calc = { let add = (x, y)

    => x + y; }; Calc.add(4, 5);
  20. 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 */
  21. Component let component = ReasonReact.statelessComponent("App"); let make = _children =>

    { ...component, render: _self => <div> <h1> (ReasonReact.string("Welcome!")) </h1> </div>, };
  22. Component let component = ReasonReact.statelessComponent(“App"); let make = (~message, _children)

    => { ...component, render: _self => <div> (ReasonReact.string(message)) </div>, };
  23. Component let component = ReasonReact.statelessComponent("App"); let make = (~fooProp, ~barProp,

    _children) => { ...component, /* render and lifecycle methods go here */ };
  24. 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>, };
  25. 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>, };
  26. 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>, };
  27. 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>, };
  28. 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>, };
  29. 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>, };
  30. 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>, };
  31. 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>, };
  32. type person = { name: string, age: int, }; let

    people: array(person) = [| {name: "Matt", age: 26}, {name: "Czysty", age: 6}, |]; Arrays
  33. 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>, };
  34. 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>, };
  35. 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
  36. Modify index.js import { app } from './src/App'; import React

    from 'react'; import { AppRegistry } from 'react-native'; AppRegistry.registerComponent('MyReasonApp', () => app);
  37. 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>;