Skip to content

doolse/purescript-reactnative

Folders and files

NameName
Last commit message
Last commit date

Latest commit

f0f9dc8 · Aug 14, 2018

History

79 Commits
Aug 13, 2018
Jun 12, 2018
Apr 17, 2017
Jun 12, 2018
Aug 14, 2018
May 19, 2018
Jun 14, 2018
Jun 12, 2018
Jun 12, 2018
Jun 12, 2018

Repository files navigation

purescript-reactnative

Latest release Travis Build

Purescript bindings for react-native

Goals

React-native is a fast moving javascript project which is frequently released (monthly at the time of writing). Much too fast for me to realistically keep all the purescript bindings continually up-to-date, so the goals are:

  • Keep up to date with purescript language releases.

  • Keep the official React Native docs as the best place to go for help. This will be acheived by:

  • Using record types for property passing.

  • Use newtype | foreign import data + smart constructors for property types.

  • Have unsafe versions of all the component functions, so if the library is lagging behind or the component does not yet have a safe version, it's still possible to use the library without too much hassle.

  • Stay event framework agnostic. This is acheived by using EffectFnX to model the event callbacks. I have also made a very small and simple library for working with react event handling (based on ReaderT) purescript-dispatcher-react.

Examples and Naming conventions

All component functions follow the naming convention of:

  • image - The most common properties
  • image_ - Only mandatory properties
  • image' - Mandatory properties and all optional properties - uses purescript row constraints to allow a single record to be passed in.
  • imageU - Unsafe, takes any properties

Enum property types will either be accessible through functions with the name of the enum:

newtype FlexDirection = FlexDirection String

row :: FlexDirection
row = FlexDirection "row"

rowReverse :: FlexDirection
rowReverse = FlexDirection "row-reverse"

column :: FlexDirection
column = FlexDirection "column"

columnReverse :: FlexDirection
columnReverse = FlexDirection "column-reverse"`

or a record which has a field for each value in the enum:

newtype KeyboardDismissMode = KeyboardDismissMode String
keyboardDismissMode :: {
    none :: KeyboardDismissMode
  , interactive :: KeyboardDismissMode
  , onDrag :: KeyboardDismissMode
}
keyboardDismissMode = {
    none: KeyboardDismissMode "none"
  , interactive: KeyboardDismissMode "interactive"
  , onDrag: KeyboardDismissMode "on-drag"
}

If you want to examples check out the code in the purescript-reactnative port of the Movies example app which comes with the react-native source code.

https://github.com/doolse/purescript-reactnative-example

Styles

Styles are defined using arrays of StyleProps and you can create a stylesheet simply by creating a record which contains these styles defined with staticStyles:

sheet :: { searchBar :: Styles
, searchBarInput :: Styles
, spinner :: Styles
, icon :: Styles
}
sheet = {
  searchBar: staticStyles [
    flexDirection row,
    alignItems center,
    backgroundColor $ rgbi 0xa9a9a9,
    height 56
  ],
  searchBarInput: staticStyles [
    flex 1,
    fontSize 20,
    fontWeight bold,
    color white,
    height 50,
    padding 0,
    backgroundColor transparent
  ],
  spinner: staticStyles [
    width 30,
    height 30,
    marginRight 16
  ],
  icon: staticStyles [
    width 24,
    height 24,
    marginHorizontal 8
  ]
}

Platform specific code

The decision to not do anything special with the type system concerning platform specific components is because:

  • a) Usually it very obvious from the component name
  • b) It would be a significant amount of extra work and type signature noise and I don't think the benefits justify it.

Having said that, platform specific properties have been separated into sub properties for clarity. For example:

type ViewProps eff = {
    style :: Styles
    -- More platform neutral properties
  , ios :: {
        shouldRasterizeIOS :: Boolean
    },
  , android :: {
        needsOffscreenAlphaCompositing :: Boolean
    }
}
import ReactNative.Components (iosProps,androidProps)

main = view' {accessible:true, android:androidProps {collapsable:true}, ios:iosProps {shouldRasterizeIOS:true} }

Getting started - Hello World

This is a barebones starter "in accordance with the ancient traditions of our people" meant to parallel the example on facebook's react-native docs.

Firstly, install the react native cli if you don't have it already, and then start a barebones react-native project:

npm install -g react-native-cli
react-native init HelloWorld

Also add in the basic purescript project structure to the project.

cd HelloWorld
pulp init --force

Install purescript react native dependency:

bower install purescript-reactnative --save

Replace the contents of src/Main.purs with

module Main where

import Prelude

import Effect (Effect)
import React (ReactClass, statelessComponent)
import ReactNative.API (registerComponent)
import ReactNative.Components.Text (text_)

app :: forall p. ReactClass {|p}
app = statelessComponent render
  where
  render _ = text_ "Hello World"
 
main :: Effect Unit
main = do
  registerComponent "HelloWorld" app

Then from your project root, build the purescript project and output it to index.js

pulp build --to index.js

And that's it! Fire up an emulator (e.g. android avd) or connect a device and launch your app:

react-native run-android

Component support table

The plan is to initially support a subset of the components fully, and provide unsafe functions for many of the others. Type safe versions of the components are created based off the react-native documentation, this table shows the current status:

Component Supported
View [x]
SafeAreaView [x]
Text [x]
TextInput [x]
Switch [x]
Touchable* [x]
Picker [x]
Slider [x]
ActivityIndicator [x]
ListView [x]
ScrollView [x]
Image [x]
RefreshControl [x]
Button [x]
NavigatorIOS [x] *
DrawerLayoutAndroid [x]
ToolbarAndroid [x]
Modal [x]
ProgressBarAndroid [x]
DatePickerIOS -
KeyboardAvoidingView -
MapView -
ProgressViewIOS -
SegmentedControlIOS -
StatusBar -
SnapshotViewIOS -
TabBarIOS -
TabBarIOSItem -
ViewPagerAndroid -
WebView -
API Version
alert [x]
color [x]
ListViewDataSource [x]

Anything marked with * may not have 100% coverage of API calls yet.

Contributors

  • Jolse Maginnis (doolse@gmail.com @doolse2)
  • Jens Krause (@sectore)
  • Nicholas Brady (nick.brady@smartrac-group.com)
  • Don Abrams (don.abrams@smartrac-group.com)
  • Ben Fleisch (bfly2000@gmail.com)
  • Alexander Obi (alexander.obi@smartrac-group.com)