Last active
February 12, 2017 11:21
-
-
Save bodhi/a1327cda84cec1ac37978b5189b22f48 to your computer and use it in GitHub Desktop.
React Native backend for Pux
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use strict"; | |
var React = require("react"); | |
var ReactNative = require("react-native") | |
var AppRegistry = ReactNative.AppRegistry; | |
function reactClass(htmlSignal) { | |
return React.createClass({ | |
componentWillMount: function () { | |
var ctx = this; | |
htmlSignal.subscribe(function () { | |
ctx.forceUpdate(); | |
}); | |
}, | |
render: function () { | |
return htmlSignal.get() | |
} | |
}); | |
} | |
exports.registerComponent = function (name) { | |
return function registerComponent(signal) { | |
var elem = reactClass(signal); | |
AppRegistry.registerComponent(name, function() { return elem }); | |
return function () {}; | |
} | |
} | |
var fromReact = function (comp) { | |
return function (attrs) { | |
return function (children) { | |
if (Array.isArray(children[0])) children = children[0]; | |
var props = attrs.reduce(function (obj, attr) { | |
var key = attr[0]; | |
var val = attr[1]; | |
obj[key] = val; | |
return obj; | |
}, {}); | |
return React.createElement.apply(null, [comp, props].concat(children)) | |
}; | |
}; | |
}; | |
exports.view = fromReact(ReactNative.View); | |
exports.text = fromReact(ReactNative.Text); | |
exports.raw = function (text) { | |
return text; | |
}; | |
exports.attr = function (key) { | |
return function (val) { | |
return [key, val]; | |
}; | |
}; | |
exports.listView = function(render) { | |
return function(list) { | |
var ds = new ReactNative.ListView.DataSource({ rowHasChanged: function(a, b) { return a != b }}); | |
var l = ds.cloneWithRows(list); | |
return fromReact( | |
function(props) { | |
return React.createElement(ReactNative.ListView, Object.assign({}, { renderRow: render, dataSource: l }, props)); | |
} | |
) | |
} | |
} | |
var test = require("../../temp").default | |
exports.test = fromReact(test); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Native (app) where | |
import Prelude (Unit, bind, ($), (+), (-), show, (<>), (<<<), pure, map) | |
import Control.Monad.Eff (Eff) | |
import Pux.Base (start, Update, element, noEffects, EffModel) | |
import Pux.Html.Elements (Attribute) | |
import Data.Function.Uncurried (runFn3) | |
import Control.Monad.Eff.Exception (EXCEPTION) | |
import Signal (Signal, (~>)) | |
import Signal.Channel (CHANNEL) | |
import Signal.Time (every) | |
import Data.List | |
import Control.Monad.Aff (attempt) | |
import Network.HTTP.Affjax (AJAX, get) | |
import Data.Either | |
import Data.Argonaut.Decode (class DecodeJson, decodeJson, (.?)) | |
import Data.Foldable (foldl) | |
foreign import data Native :: * -> * | |
foreign import registerComponent :: forall a eff. String -> Signal (Native a) -> Eff eff Unit | |
foreign import data Text :: * -> * | |
data NativeText a = N (Native a) | Text String | |
type Element a = Array (Attribute a) -> Array (Native a) -> Native a | |
foreign import view :: forall a. Element a | |
foreign import test :: forall a. Element a | |
text :: forall a. Array (Attribute a) -> Array (NativeText a) -> Native a | |
text a c = _text a $ map toNative c | |
where toNative :: NativeText a -> Native a | |
toNative (N a) = a | |
toNative (Text s) = raw s | |
foreign import _text :: forall a. Array (Attribute a) -> Array (Native a) -> Native a | |
foreign import listView :: forall item a. (item -> Native a) -> Array item -> Element a | |
-- Bad type, it needs to be embedded inside <Text> | |
foreign import raw :: forall a. String -> Native a | |
foreign import attr :: forall a v. String -> v -> Attribute a | |
-------------------------------------------------- | |
data Action = RequestTodos | ReceiveTodos (Either String Todos) | |
type State = | |
{ todos :: Todos | |
, status :: String } | |
type Todos = Array Todo | |
newtype Todo = Todo | |
{ id :: Int | |
, title :: String } | |
instance decodeJsonTodo :: DecodeJson Todo where | |
decodeJson json = do | |
obj <- decodeJson json | |
id <- obj .? "id" | |
title <- obj .? "title" | |
pure $ Todo { id: id, title: title } | |
fetchTodos = do | |
res <- attempt $ get "https://jsonplaceholder.typicode.com/users/1/todos" | |
let decode res = decodeJson res.response :: Either String Todos | |
let todos = either (Left <<< show) decode res | |
pure $ ReceiveTodos todos | |
update :: Action -> State -> EffModel State Action (ajax :: AJAX) | |
update (ReceiveTodos (Left err)) state = | |
noEffects $ state { status = "Error fetching todos: " <> show err } | |
update (ReceiveTodos (Right todos)) state = | |
noEffects $ state { todos = todos, status = "Todos" } | |
update (RequestTodos) state = | |
{ state: state { status = "Fetching todos..." } | |
, effects: [ fetchTodos ] | |
} | |
wrapper = view [ attr "style" { flex: 1, alignItems: "stretch", backgroundColor: "red", paddingTop: 60 } ] | |
todoView :: Todo -> Native Action | |
todoView (Todo { id, title }) = text [] [ Text (show id <> ": " <> title) ] | |
v :: State -> Native Action | |
v { todos, status } = wrapper [ listView todoView todos [] [] | |
, text [] [ Text status ] | |
, test [] [] | |
] | |
--u :: String -> Native Action | |
--u s = text [] [ s ] | |
app :: Eff (err :: EXCEPTION, channel :: CHANNEL, ajax :: AJAX) Unit | |
app = do | |
a <- start | |
{ initialState: { todos: [Todo { title: "initial", id: 0 }] | |
, status: "" | |
} | |
, update | |
, view: v | |
, inputs: [ | |
-- every 5000.0 ~> \_ -> RequestTodos | |
] | |
} | |
registerComponent "mobile" a.html |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Cross-reference: alexmingoia/purescript-pux#100