This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-05-10
Channels
- # aws (3)
- # beginners (186)
- # boot (25)
- # cider (2)
- # cljsrn (57)
- # clojure (161)
- # clojure-boston (1)
- # clojure-dusseldorf (11)
- # clojure-italy (5)
- # clojure-russia (20)
- # clojure-serbia (1)
- # clojure-spec (10)
- # clojure-uk (16)
- # clojurescript (207)
- # community-development (86)
- # core-async (2)
- # cursive (40)
- # datascript (1)
- # datomic (2)
- # editors (5)
- # emacs (8)
- # funcool (1)
- # gsoc (2)
- # hoplon (2)
- # jobs (5)
- # leiningen (3)
- # liberator (18)
- # luminus (18)
- # off-topic (106)
- # om (2)
- # onyx (5)
- # pedestal (7)
- # powderkeg (7)
- # re-frame (7)
- # remote-jobs (1)
- # ring-swagger (4)
- # rum (5)
- # slack-help (1)
- # untangled (11)
- # yada (48)
Hey all. I'm trying to get navigation running - I'm pretty new to RN, let alone to cljsrn - and I just can't make it work. I'm using rum/re-natal and I'm trying out (recommended?) https://reactnavigation.org/ . This is how far I got:
(ns my.ns.android.core
(:require-macros [rum.core :refer [defc]])
(:require [re-natal.support :as support]
[rum.core :as rum]))
(set! js/window.React (js/require "react"))
(def ReactNative (js/require "react-native"))
(def ReactNavigation (js/require "react-navigation"))
(def stack-nav (.-StackNavigator ReactNavigation))
(def app-registry (.-AppRegistry ReactNative))
(def text (partial create-element (.-Text ReactNative)))
(defc HelloScreen
[]
(text "Hello, navigation"))
(defc AnotherScreen
[]
(text "Hello, another"))
(def App (stack-nav. (clj->js {:Home {:screen (:rum/class (meta HelloScreen))}})))
(defonce root-component-factory (support/make-root-component-factory))
(defn mount-app []
(support/mount App)
(init-user-location)
(state/retreive-markers))
(defn init []
(mount-app)
(.registerComponent app-registry "fleeman" (fn [] root-component-factory)))
However, this returns an error (see screenshot below)
So it seems App
is not a react element.
I don’t know rum, but it looks like (:rum/class
is returning a class?
ok, so here are a few new things to try:
1. Make an element from the class: (support/mount (create-element App))
Better, but doesn't show the component.
2. Replace (:rum/class (meta HelloScreen))
with HelloScreen
(a React Native component):
React Native tells me it's not a react component... (that's why I had to do the weird thing with (:rum/class (meta ...))
)
Yeah, React Navigation needs react components to render.
Well, right, but HelloScreen
is a react component (or at least, it should be, according to the rum docs)
So, this part (.registerComponent app-registry "fleeman" (fn [] root-component-factory)))
needs to return a react component. What’s the root-component-factory doing?
Yeah, that's the helper for rum, apparently:
(ns re-natal.support
"Helpers and adapters to be able to mount/remount Rum components in a React Native application.")
(def React (js/require "react"))
(def create-class (.-createClass React))
(def create-factory (.-createFactory React))
(defonce root-component (atom nil))
(defonce mounted-element (atom nil))
(defn make-root-component-factory
"Returns a React Native component factory fn for the root componenet singleton"
[]
(create-factory
(create-class
#js {:getInitialState
(fn []
(this-as this
(if-not @root-component
(reset! root-component this)
(throw (js/Error. "ASSERTION FAILED: re-natal.support root component mounted more than once.")))))
:render
(fn [] @mounted-element)})))
(defn mount
"A modified version of rum.core/mount to work with React Native and re-natal.
Since React Native's root component is a singleton, mount doesn't apply in the
context of a DOM element (like in React), but applies globally to the app.
This function mounts/replaces the current "
[element]
(reset! mounted-element element)
(when @root-component
(.forceUpdate @root-component)))
it basically mounts the root component.
I'm really new to RN, and thought navigation would be straight forward 😛. It seems there are some libs around, and it's not that easy 😛.
Which is App
?
(def App (stack-nav. (clj->js {:Home {:screen (create-element HelloScreen)}})))
That's the StackNavigator
(def ReactNavigation (js/require "react-navigation"))
(def stack-nav (.-StackNavigator ReactNavigation))
Nah. Navigation with React Native has never been straightforward. Even on vanilla RN.
Yeah... pretty weird, since I don't need complex navigation. It's just 2 (max 3) 'screens'
swiping from one to another (or going to another one by pushing a button).
I've been thinking of just doing this manually with the RN animations API, but it all looks a bit weird to me. Anyway, not sure how to make it work.
Well, I think you need a react component for the :screen
prop. Not sure if an element will work.
ok. let's see how far I can get (`HelloScreen` is actually a react component, or it should be)
Yeah. I started with baby steps. Made everything normal react components and just tried to get basic stuff displaying at first.
well, yes, the basics are ok... I was at the stage to put it all together and and navigation 🙂
oh, ok... got something working.
nice.
(defc HelloScreen
[]
(view {:style {:alignItems "stretch"
:flex 1}}
(text {:style {:fontSize 30
:fontWeight "100"
:marginBottom 20
:textAlign "center"}}
"Hello")))
(defc AnotherScreen
[]
(text "Hello, another"))
(def App (stack-nav. (clj->js {:Home {:screen (:rum/class (meta HelloScreen))}})))
(defonce root-component-factory (support/make-root-component-factory))
(defn mount-app []
(support/mount (create-element App))
(init-user-location)
(state/retreive-markers))
Now, next step: how to add the titles...
class HomeScreen extends React.Component {
static navigationOptions = {
title: 'Welcome',
};
render() {
return <Text>Hello, Navigation!</Text>;
}
}
Or, how to add static navigationOptions
? (I suppose I don't have to worry about the warning - as far as I know, it's something about RN 0.44?)Yeah. I think they are changing the back behavior on Android
Here’s what I’m using for navigationOptions:
(defn screen
"If navigationOptions are specified append to the react-component"
[react-component navigationOptions]
(when (and navigationOptions (not= navigationOptions :cljs.spec/invalid))
(aset react-component "navigationOptions" (clj->js navigationOptions)))
react-component)
right... aset
is the thing I was looking for, I guess.
It feels kinda hacky, but since they insist on using “ES6 Classes” which are just hacks you gotta do it.
right.
Ugh. I wish my navigation library was in better shape. I’m in the process of creating a general purpose cljs wrapper for React Navigation using spec
. Then specific libraries can extend the base layer.
I'd love a 'general purpose cljs wrapper' 🙂
(defc HelloScreen < rum/reactive
[]
(view {:style {:alignItems "stretch"
:flex 1}}
(text {:style {:fontSize 30
:fontWeight "100"
:marginBottom 20
:textAlign "center"}}
"Hello, navigation")))
(def HelloScreenClass (:rum/class (meta HelloScreen)))
(aset HelloScreenClass "navigationOptions" (clj->js {:title "Welcome!"}))
looks hacky in many ways, but well, it works 😛
Okay, this is definitely a work in progress, but maybe these gists will help you? https://gist.github.com/seantempesta/432ab1e60d2216a668dc2c1bd9fa2066 https://gist.github.com/seantempesta/33edc5d847542453e6ec7caeae05721a
Basically, the base is just a bunch of specs that explain what react navigation is expecting and has simple conformers for converting react components to react elements when needed.
really nice.
The reagent version inherits the base and extends the conforming specs to also allow reagent components and just transparently converts them to normal react components or elements
So it'll be a matter of translating the reagent
-specific functions to other wrappers. cool.
yeah. Basically the functions say what they should be returning. Either a react component or an element or a function that will return a component or element. With the latter you can do all the (clj->js
conversions for props so you can just keep everything in clojurescript.
I was hoping to save everyone from re-inventing the wheel and then we could have rum and om wrappers as well.
yeah, true.
navigation should be pretty straight forward...
ha. should is the key word there. but it is getting a lot better. It used to be even worse if you can believe it.
well, yes, I believe it (although I actually can't believe it - that's weird)
Anyway, half the battle for me was just defining all of the specs. Once it was clear what every function actually wanted (because the docs are kinda confusing) I made faster progress. Hopefully those will help you.
It will... thanks a lot!
@dos: in production? Not yet. But I plan to.