4.0.1 • Published 7 years ago

@purescript/reactnative v4.0.1

Weekly downloads
-
License
MIT
Repository
github
Last release
7 years ago

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 EffFnX to model the event callbacks. There will be additional libraries for your favourite action library - e.g. purescript-reactnative-thermite I have also made a very small and simple library for dispatching react actions 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 Control.Monad.Eff (Eff)
import React (ReactClass, Render, createClass, getProps, spec)
import ReactNative.API (REGISTER, registerComponent)
import ReactNative.Components.Text (text_)

render :: forall props state eff. Render props state eff
render ctx = do
            _ <- getProps ctx  -- get props from context if needed
            pure(text_ "Hello World")

app :: forall p. ReactClass p
app = createClass $ spec {} render

main :: forall e. Eff (register:: REGISTER | e) Unit
main = do
  registerComponent "HelloWorld" app

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

pulp build --to index.android.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:

ComponentSupported
Viewx
Textx
TextInputx
Switchx
Touchable*x
Pickerx
Sliderx
ActivityIndicatorx
ListViewx
ScrollViewx
Imagex
RefreshControlx
Buttonx
Navigatorx *
NavigatorIOSx *
DrawerLayoutAndroidx
ToolbarAndroidx
Modalx
ProgressBarAndroidx
DatePickerIOS-
KeyboardAvoidingView-
MapView-
ProgressViewIOS-
SegmentedControlIOS-
StatusBar-
SnapshotViewIOS-
TabBarIOS-
TabBarIOSItem-
ViewPagerAndroid-
WebView-
APIVersion
alertx
colorx
ListViewDataSourcex
NavigationExpirementalx *

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)