React-native-web: Usage with Flow

Created on 7 Mar 2018  路  11Comments  路  Source: necolas/react-native-web

What is the recommended way when we have no react-native in package.json yet?

// $FlowFixMe Flow correctly detects there is no react-native.
import { StyleSheet, Text, View } from 'react-native';

screen shot 2018-03-07 at 02 53 10

Most helpful comment

Hi @steida , no problem happy to try and help where I can.

I'd like to amend my previous answer by adding /src to the end of the options remap, it should read
module.name_mapper='^react-native$' -> '<PROJECT_ROOT>/node_modules/react-native-web/src'

By doing this, we instruct flow to read flow types for react-native from the node_modules/react-native-web/src directory

Since react-native-web publishes both the dist AND the src we can read flow types from the src folder. This is because RNW uses both PropTypes and Flow in it's source.

This will get flow to properly read all the types as they exist in react-native-web

Note that the API's are slightly different though between RN and RNW, so there may be some inconsistencies.

For example, the StatusBar component in RN has a function setHidden(hidden: boolean, animation: StatusBarAnimation) which takes two args.
In RNW, StatusBar is basically a stub component, and it's setHidden() function has no args, since technically you would not use StatusBar on the web.

Additionally, for this to work, we must mark src/index.js as @flow. I had done this locally when getting it to work, but we should PR that change back. You can try this locally to get up and running

A typed lib-def would be fantastic. There is also flow-copy-source https://github.com/AgentME/flow-copy-source which renames and copies source files into your dist. It names files such that flow will pick them up, eg StatusBar.js.flow
That's up to the author on which approach they prefer

All 11 comments

I still don't know whether React Native should be separated app in a browser app or we it should share (have a universal) package.json. I feel it should be separated app. Then, what is the recommended way for Flow in a browser?

Hi,

You can utilize the module.name_mapper option in your .flowconfig to resolve this

[options]
# Point react-native (alias in babel) to react-native-web for flow support
module.name_mapper='^react-native$' -> '<PROJECT_ROOT>/node_modules/react-native-web'

This simply points any references to react-native to the react-native-web source and uses it's flow types/inference

@SRandazzo Thank you. I don't understand how it should help. Do you have any example repo? The problem is we need the real React Native repo in another dir I suppose.

I've been working on filling in a libdef for react-native-web, since we use it without react-native and would like to not get hit by the web-only props/APIs.

@necolas is that something you'd like to provide in this package, or would you prefer it submitted to flow-typed?

Hi @steida , no problem happy to try and help where I can.

I'd like to amend my previous answer by adding /src to the end of the options remap, it should read
module.name_mapper='^react-native$' -> '<PROJECT_ROOT>/node_modules/react-native-web/src'

By doing this, we instruct flow to read flow types for react-native from the node_modules/react-native-web/src directory

Since react-native-web publishes both the dist AND the src we can read flow types from the src folder. This is because RNW uses both PropTypes and Flow in it's source.

This will get flow to properly read all the types as they exist in react-native-web

Note that the API's are slightly different though between RN and RNW, so there may be some inconsistencies.

For example, the StatusBar component in RN has a function setHidden(hidden: boolean, animation: StatusBarAnimation) which takes two args.
In RNW, StatusBar is basically a stub component, and it's setHidden() function has no args, since technically you would not use StatusBar on the web.

Additionally, for this to work, we must mark src/index.js as @flow. I had done this locally when getting it to work, but we should PR that change back. You can try this locally to get up and running

A typed lib-def would be fantastic. There is also flow-copy-source https://github.com/AgentME/flow-copy-source which renames and copies source files into your dist. It names files such that flow will pick them up, eg StatusBar.js.flow
That's up to the author on which approach they prefer

@SRandazzo Thank you! It seems it works. But, because I want to integrate React Native into Next.js, I will try to read types from /native sub dir.

UPDATE: Hmm, it's not probably possible, because React Native flow config is different. module.system=haste etc.

Hmm, haste does noting it seems.

This is an example of working flowconfig for universal React and React Native app with shared package.json https://github.com/este/este

[ignore]
.*/node_modules/iterall/.*
.*/node_modules/bcryptjs/.*
.*/node_modules/config-chain/.*

; RN
; We fork some components by platform
.*/*[.]android.js
; Ignore "BUCK" generated dirs
<PROJECT_ROOT>/\.buckd/
; Ignore unexpected extra "@providesModule"
.*/node_modules/.*/node_modules/fbjs/.*
; Ignore duplicate module providers
; For RN Apps installed via npm, "Libraries" folder is inside
; "node_modules/react-native" but in the source repo it is in the root
.*/Libraries/react-native/React.js
; Ignore polyfills
.*/Libraries/polyfills/.*
; Ignore metro
.*/node_modules/metro/.*

; Web + RN temp fix. The problem is duplicated providers.
; TODO: Recheck
.*/node_modules/babel-plugin-relay/.*
.*/node_modules/relay-runtime/.*
.*/node_modules/relay-compiler/.*
; We have real RN types
.*/node_modules/react-native-web/.*

[untyped]
; TODO: Recheck
; https://github.com/facebook/draft-js/issues/1496#issuecomment-353895318
.*/node_modules/draft-js/lib/DraftEditor.react.js.flow
; https://github.com/facebook/draft-js/issues/1621
.*/node_modules/draft-js/lib/ContentBlock.js.flow
.*/node_modules/draft-js/lib/ContentBlockNode.js.flow
; RN
.*/node_modules/react-native/Libraries/Lists/SectionList.js
.*/node_modules/react-native/Libraries/Lists/FlatList.js
.*/node_modules/react-native/Libraries/CameraRoll/CameraRoll.js

[include]

[libs]
; RN
node_modules/react-native/Libraries/react-native/react-native-interface.js
node_modules/react-native/flow/
node_modules/react-native/flow-github/

[lints]
all=error
unclear-type=off

[options]
include_warnings=true

; RN
emoji=true
; It looks like it does not nothing.
module.system=haste
munge_underscores=true
module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub'
module.file_ext=.js
module.file_ext=.jsx
module.file_ext=.json
module.file_ext=.native.js
suppress_type=$FlowIssue
suppress_type=$FlowFixMe
suppress_type=$FlowFixMeProps
suppress_type=$FlowFixMeState
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(<VERSION>\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(<VERSION>\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+
suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError

@paularmstrong would you mind sharing your interface definition, even if that's a WIP? I would like to help on this. I have a project RNW only I don't have flow support and would like to add it.

@necolas are you interested in a effort via a flow-typed definition? We could also try to work on the codebase so flow understands it without any user effort

@MoOx It's not totally complete and there may be some bugs, but it's here: https://gist.github.com/paularmstrong/f60b40d16fc83e1e8e532d483336f9bb

Keep in mind: react-native-web _does_ have quite a bit of flow definitions in source. You could point flow to the src directory in your node_modules/react-native-web. We don't, as we want to have things be a bit more strict. It might be silly, but it's where we're at right now.

@steida works (kind of) if you have RN + RNW (but won't work for RNW specificities). If you import "react-native-web" directly you have to use an interface or a mapping.

@paularmstrong thanks!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

PaulBGD picture PaulBGD  路  4Comments

rohanprabhu picture rohanprabhu  路  3Comments

bcpugh picture bcpugh  路  3Comments

blairio picture blairio  路  3Comments

EvanBacon picture EvanBacon  路  3Comments