fable-compiler / fable-react-native

Fable bindings and helpers for React Native projects
Apache License 2.0
49 stars 11 forks source link

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

Closed playfulThinking closed 3 years ago

playfulThinking commented 3 years ago

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 https://github.com/SAFE-Stack/SAFE-Nightwatch/pull/66#issuecomment-465962587 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,
      },
    }),
  },
};
playfulThinking commented 3 years ago

OK, I seem to have solved the problem. My index.js should not have had this line:

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