GithubHelp home page GithubHelp logo

fable-compiler / fable-react-native Goto Github PK

View Code? Open in Web Editor NEW
47.0 10.0 11.0 534 KB

Fable bindings and helpers for React Native projects

License: Apache License 2.0

F# 99.75% Batchfile 0.07% Shell 0.18%

fable-react-native's Introduction

Fable.React.Native

Fable bindings and helpers for React Native projects.

See SAFE-Nightwatch for a Fable RN app sample.
See How-to for a short step-by-step guide to getting started developing mobile apps with F# and Fable in React Native.

fable-react-native's People

Contributors

alfonsogarciacaro avatar aviavni avatar ddunlea avatar forki avatar iyegoroff avatar mangelmaxime avatar mohan-win avatar tforkmann avatar y2k avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fable-react-native's Issues

How to get user's current position?

Hi there,

I'm trying to get the current position of my phone doing this: Fable.Import.ReactNative.Globals.Geolocation.getCurrentPosition (fun pos -> Browser.console.log ("currentPosition", pos))

But this yields the following error:
undefined is not an object (evaluating _reactNative.Geolocation.getCurrentPosition

How can I do it?

Hooks and function components?

fable-react supports function components but it seems they can't be used in fable-react-native. Am I missing something here (likely, I'm new to f#)? My react-native app crashes if I try to use Fable.React.FunctionComponent.Of(...)

 ERROR    TypeError: module.hot.addStatusHandler is not a function. (In 'module.hot.addStatusHandler(function (status) {
        if (status === "apply") (function () {
          cache.clear();
        })();
      })', 'module.hot.addStatusHandler' is undefined)
[Wed Jul 22 2020 11:36:26.377]  ERROR    Invariant Violation: Module AppRegistry is not a registered callable module (calling runApplication)
[Wed Jul 22 2020 11:36:26.377]  ERROR    Invariant Violation: Module AppRegistry is not a registered callable module (calling runApplication)
[Wed Jul 22 2020 11:36:26.377]  ERROR    Invariant Violation: Module AppRegistry is not a registered callable module (calling unmountApplicationComponentAtRootTag)
[Wed Jul 22 2020 11:36:26.378]  ERROR    Invariant Violation: Module AppRegistry is not a registered callable module (calling runApplication)

Questions about how to write bindings and a few other small things.

Hi, I'm working on POC using fable-react-native so we can see if this is a good approach for our new app, and I have a few questions that I didn't know where else to ask.

First, we need to use Mapbox, I'm actually trying to use this component https://github.com/mapbox/react-native-mapbox-gl/blob/master/docs/MapView.md and of course I'm trying to write my first F# bindings for it. In its demo the component is imported this way import MapboxGL from '@mapbox/react-native-mapbox-gl'; and used this way:

<MapboxGL.MapView
          showUserLocation={true}
          zoomLevel={12}
          userTrackingMode={MapboxGL.UserTrackingModes.Follow}
          styleURL={this.state.styleURL}
          style={sheet.matchParent}
        />

Here's what I came up with that is not working yet, and I was wondering if you could help me with it.

type MapViewProps =
    | ShowsUserLocation of bool
    | ZoomLevel of int
    | StyleURL of string
    | Style of string


let inline mapView (props: MapViewProps list) : ReactElement =    
    ofImport "MapView" "@mapbox/react-native-mapbox-gl" (keyValueList CaseRules.LowerFirst props) []

Also, I'm using as a base the SAFE-Nightwatch demo, and I was wondering if it's possible to debug using vscode, I was not able to do so, so far.

Finally, I'm starting the app using build.cmd debug and if I stop the process using Ctrl+C I can never seem to start it again, some process is kept hung up and I cannot restart the app again.

I appreciate any directions you can give me, thank you

Split "extra" modules into their own packages

Having every possible react-native module just as an "extra" module makes using rn with fable very cumbersome

1) Versioning

  • Some of these packages depend on a specific version of react-native but here they are all available in this one single package (see for example notice of react-native-fs) and they could be easily incompatible with the current version of rn.
  • They are not compatible with Femto making it hard to find and use different versions of an "extra" package

2) Discoverability

Using the auto-opened "Helpers" module is the most unhelpful thing to have, because the user will have functions that are globally available and the only way to find them is by having to look in the source code, for example the "helper" of device info:

[<AutoOpen>]
module Helpers =
    let private deviceInfo: obj = importDefault "react-native-device-info"
    /// Gets the API level.
    let getAPILevel () : int =
        deviceInfo?getAPILevel() |> unbox
    /// Gets the application name.
    let getApplicationName () : string =
        deviceInfo?getApplicationName() |> unbox

Please replace instead with DeviceInfo as [<RequireQualifiedAccess>], i.e.

[<RequireQualifiedAccess>]
module DeviceInfo =
    let private deviceInfo: obj = importDefault "react-native-device-info"
    /// Gets the API level.
    let getAPILevel () : int =
        deviceInfo?getAPILevel() |> unbox
    /// Gets the application name.
    let getApplicationName () : string =
        deviceInfo?getApplicationName() |> unbox

3) The use of ts2fable-like constructs

Going through some of the extra packages, I still see U<...> being used instead of proper arguments, for example in here where it is not obvious how the location of the SQLite database can be instantiated from a float

4) Adhoc Bindings

for example react-native-fs now only includes two functions:

[<AutoOpen>]
module Helpers =
    [<Import("default","react-native-fs")>]
    let private fileSystem = obj()
    let deleteFile (uri:string) : unit = fileSystem?unlink(uri) |> ignore
    let getBase64File (uri:string) : JS.Promise<string> = fileSystem?readFile(uri,"base64") |> unbox

This is not helpful for the users of the library and they are better off writing these functions in their application code instead of having two random functions

5) Zero docs

Might be the biggest reason that it is hard to get started with this library, even though it has a really high potential next to electronjs that there is no docs on the "extra" packages

@forki @alfonsogarciacaro @MangelMaxime

Why are breaking changes increment the PATCH number of the package?

@forki The change log clearly states that the changes are breaking:

2.5.1

  • BREAKING: use NetInfo from react-native-netinfo

2.5.0

2.4.1

  • BREAKING: use ToolbarAndroid from @react-native-community/toolbar-android

2.3.0

  • BREAKING: Put onActionSelected into properties of ToolbarAndroid

Yet there is no single update in the major version? This still ties up to #54 where now we not even considering communicating how version changes affect user code

cc @MangelMaxime @alfonsogarciacaro

Fable 2.0 support

Hello,

I was wondering if there were plans to get this library up to date with the newest Fable 2.0
Otherwise I will start looking into what is needed to get this working.

Thanks

Working with gestures

Hey there, I'm trying to work with some animation stuff and I'm having some difficulties. You may have seen my PR alread but I do have another issue that I'd like to understand how to fix it.

The interface IViewProperties inherits from IGestureResponderHandlers

inherit IGestureResponderHandlers

And I was wondering how I could pass it to the view.
I began creating an object:

let panResponderConfig = createEmpty<Fable.Import.ReactNative.PanResponderCallbacks>
let panResponder = RN.PanResponder.create(panResponderConfig)

But then, how am I suppose to pass panResponder.panHandlers to the view?

Usually with javascript this is done this way:

this._panResponder = PanResponder.create({ .... })
<View {...this._panResponder.panHandlers}>....</View>

How can I replicate JavaScript's spread operator and how can I pass that to IViewProperties?

Thanks

Fable 4 incompatibility

I updated a very simple project to Fable 4 and got this:

./src/fable_modules/Fable.React.Native.3.0.0-alpha001/Fable.ReactNative.Types.fs(1451,76): (1451,78) error FSHARP: The type parameter 'T is not defined. (code 39)
./src/fable_modules/Fable.React.Native.3.0.0-alpha001/Fable.ReactNative.Types.fs(1452,65): (1452,67) error FSHARP: The type parameter 'T is not defined. (code 39)

These are the lines that offend:

abstract getRowData: (obj -> U2<float, string> -> U2<float, string> -> 'T) option with get, set
abstract getSectionHeaderData: (obj -> U2<float, string> -> 'T) option with get, set

This seems to be related to this: fable-compiler/Fable#3248
Apparently this is not a compiler error, but an illegal construction the CLR.

I don't know what these functions do, nor how to fix the declarations. Anybody?

Thanks much!

Missing currentHeight static property for StatusBar

According to the RN docs the StatusBar api has a static member called currentHeight that is available only to Android but its available on the main StatusBar object.

I thought of adding it here:

abstract setTranslucent: (bool -> unit) with get, set

with something like:
abstract currentHeight: float with get

but I'm not sure if it's the right approach, if it is, I'm happy to send a PR or with whatever you think is best

yarn add --dev fable-splitter fable-compiler + Incorrect peer dependency

I'm getting following warnings when I ran yarn add --dev fable-splitter fable-compiler in my new react native project.

warning "@react-native-community/eslint-config > @typescript-eslint/[email protected]" has incorrect peer dependency "eslint@^5.0.0".
warning "@react-native-community/eslint-config > @typescript-eslint/[email protected]" has incorrect peer dependency "eslint@^5.0.0".
warning "@react-native-community/eslint-config > [email protected]" has incorrect peer dependency "eslint@^3.0.0 || ^4.0.0 || ^5.0.0".
warning "@react-native-community/eslint-config > [email protected]" has incorrect peer dependency "eslint@^3.17.0 || ^4 || ^5".
warning "@react-native-community/eslint-config > @typescript-eslint/eslint-plugin > [email protected]" has unmet peer dependency "typescript@>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta".

Wondering how can I resolve this ?

Can't change text color of pickerIOSItem

I use fable-react-native and I tried to change the color of pickerIOSItem. The current version of PickerIOSItemProperties doesn't allow do it. (We need to extend this type)
This issue has been already fixed in the react-native library.
PR here

Not possible to have multi styled text

Hello,

I would like to be able to have text with multi-styles. (for example some parts of the text is BOLD and some parts is italic). This requires nesting Text react elements inside another Text react element. See https://facebook.github.io/react-native/docs/text.

However, the Fable wrapper for text takes a list of TextProperties and a string text. There would need to be another API to take a list of TextProperties and other text elements. Would you be able to suggest a workaround?

Thanks for your help.

Fable.Core 3 support

Hi, I was wondering if there is a plan to support Fable.Core 3?

What is actually the state of this project? I see more and more people prefer Fabulous (Xamarin). So is this project going to be continued? Obviously there is no active development.

TextInputAndroidProperties

Hello,

I would like to use TextInputAndroidProperties.UnderlineColorAndroid for the textInput wrapper for ReactNative. However since TextInputAndroidProperties is not a ITextInputProperties, this is not possible. Is this a bug or am I doing something wrong? I am using Fable.react.native v1.7.2. Thanks for your help.

Here is my code snippet:
textInput [ TextInputProperties.Password true ; TextInputProperties.SecureTextEntry true ; TextInputProperties.AutoCorrect false ; TextInputProperties.DefaultValue "Password" ; TextInputProperties.Editable true ; TextInputAndroidProperties.UnderlineColorAndroid "transparent"
P.S. The same applies to TextInputIOSProperties.

Question about Func's

Why do you use types like Func<x, y, z> instead of (x -> y -> z) almost everywhere? It seems that second signature is easier to use:

with Func's

let renderItem (item: FlatListRenderItemInfo<'a>) =
  //...

R.flatList items
  [ RenderItem (Func<_, _>renderItem)
    KeyExtractor (Func<_, _, _>(fun item _ -> itemKey item)) ]

with arrows

let renderItem (item: FlatListRenderItemInfo<'a>) =
  //...

R.flatList items
  [ RenderItem renderItem
    KeyExtractor (fun item _ -> itemKey item) ]

In new app, getting error: "React.createElement: type is invalid..."

I'm getting this error:
Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object.
when I run the app.

I haven't been able to figure out what's going on. I did see SAFE-Stack/SAFE-Nightwatch#66 (comment) which had a similar problem, but (unless I'm misreading) that was fixed.

Any help would be greatly appreciated!

I tried to follow https://github.com/martinmoec/fable-react-native-how-to as closely as I could.
Here are the steps I took:

npx react-native init RNTestFSharp
npm install --save @react-native-community/netinfo
npx pod install
npm run-script watch
npx react-native run-ios

App.fsproj:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netstandard2.1</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <Compile Include="App.fs" />
  </ItemGroup>
  <Import Project="..\.paket\Paket.Restore.targets" />
</Project>

App.fs:

module App

open Elmish
open Elmish.React
open Elmish.ReactNative
open Fable.ReactNative

// A very simple app which increments a number when you press a button

type Model = { Counter: int }

type Message = | Increment

let init () = { Counter = 0 }, Cmd.none

let update msg model =
    match msg with
    | Increment ->
        { model with
              Counter = model.Counter + 1 },
        Cmd.none

module R = Fable.ReactNative.Helpers
module P = Fable.ReactNative.Props
open Fable.ReactNative.Props

let view model dispatch =

    R.view [] [ R.text [] "Hi there" ]

Program.mkProgram init update view
|> Program.withConsoleTrace
|> Program.withReactNative "RNTestFSharp"
|> Program.run

index.js:

/**
 * @format
 */

import { AppRegistry } from 'react-native';
import * as App from './out/App';
import { name as appName } from './app.json';

AppRegistry.registerComponent(appName, () => App);

babel.config.js:

module.exports = {
  presets: ['module:metro-react-native-babel-preset'],
};

splitter.config.js:

module.exports = {
    entry: "src/App.fsproj",
    outDir: "out",
    babel: {
        presets: ["module:metro-react-native-babel-preset"], filename: "App.js",
    },
    // The `onCompiled` hook (optional) is raised after each compilation
    onCompiled() {
        console.log("Compilation finished!")
    }
}

package.json:

{
  "name": "RNTestFSharp",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "android": "react-native run-android",
    "ios": "react-native run-ios",
    "start": "react-native start",
    "test": "jest",
    "lint": "eslint .",
    "build": "fable-splitter -c splitter.config.js --define RELEASE",
    "debug": "fable-splitter -c splitter.config.js --define DEBUG",
    "watch": "fable-splitter -c splitter.config.js -w --define DEBUG"
  },
  "dependencies": {
    "@react-native-community/netinfo": "^5.9.5",
    "buffer": "^5.6.0",
    "react": "16.13.1",
    "react-native": "0.63.2"
  },
  "devDependencies": {
    "@babel/core": "^7.8.4",
    "@babel/preset-env": "^7.11.0",
    "@babel/runtime": "^7.8.4",
    "@react-native-community/eslint-config": "^1.1.0",
    "babel-jest": "^25.1.0",
    "eslint": "^6.5.1",
    "fable-compiler": "^2.10.2",
    "fable-splitter": "^2.2.1",
    "jest": "^25.1.0",
    "metro-react-native-babel-preset": "^0.59.0",
    "react-test-renderer": "16.13.1"
  },
  "jest": {
    "preset": "react-native"
  }
}

paket.lock:

STORAGE: NONE
RESTRICTION: || (== netcoreapp3.1) (== netstandard2.0) (== netstandard2.1)
NUGET
  remote: https://www.nuget.org/api/v2
    Fable.Browser.Blob (1.1)
      Fable.Core (>= 3.0)
      FSharp.Core (>= 4.6.2)
    Fable.Browser.Dom (1.2)
      Fable.Browser.Blob (>= 1.1)
      Fable.Browser.Event (>= 1.0)
      Fable.Browser.WebStorage (>= 1.0)
      Fable.Core (>= 3.0)
      FSharp.Core (>= 4.7)
    Fable.Browser.Event (1.0)
      Fable.Core (>= 3.0)
      FSharp.Core (>= 4.5.2)
    Fable.Browser.WebStorage (1.0)
      Fable.Browser.Event (>= 1.0)
      Fable.Core (>= 3.0)
      FSharp.Core (>= 4.5.2)
    Fable.Promise (2.1)
      Fable.Core (>= 3.1.5)
      FSharp.Core (>= 4.7)
    FSharp.Core (4.7.2)
    Thoth.Json (4.1)
      Fable.Core (>= 3.1.4)
      FSharp.Core (>= 4.7)
  remote: https://api.nuget.org/v3/index.json
    Fable.Core (3.1.5)
      FSharp.Core (>= 4.7)
    Fable.Elmish (3.1)
      Fable.Core (>= 3.0)
      FSharp.Core (>= 4.6.2)
    Fable.Elmish.React (3.0.1)
      Fable.Core (>= 3.0)
      Fable.Elmish (>= 3.0)
      Fable.React (>= 5.1)
      FSharp.Core (>= 4.6.2)
    Fable.React (6.2)
      Fable.Browser.Dom (>= 1.0)
      Fable.Core (>= 3.1.5)
      FSharp.Core (>= 4.7)
    Fable.React.Native (2.6.1)
      Fable.Core (>= 3.0)
      Fable.Promise (>= 2.0)
      Fable.React (>= 5.2.3)
      FSharp.Core (>= 4.6.2)
      Thoth.Json (>= 3.1)

metro.config.js:

/**
 * Metro configuration for React Native
 * https://github.com/facebook/react-native
 *
 * @format
 */

module.exports = {
  transformer: {
    getTransformOptions: async () => ({
      transform: {
        experimentalImportSupport: false,
        inlineRequires: false,
      },
    }),
  },
};

Xcode chokes on .fable directory

Sometimes when I have Expo compile a project, and almost always when I do it in Xcode, I get import errors for every Fable library file like this:

Unable to resolve module ./.fable/fable-library.3.1.1/Types.js from /Users/michaelfremont/Documents/playthink/code/liarliar-admin/src/App.fs.js

The only way I've found to fix this is by renaming the ".fable" directory to "fable" and changing the paths in the generated fs.js files; it then complies, but this is not a workable solution.

Any ideas? Thanks much.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.