How to use StackNavigator of React Navigation in clojurescript

1.2k views Asked by At

I am new to clojurescript and reagent. I try to use react-navigation in my react-native app but I getting this error

Error rendering component (in env.main.reloader > exp_cljs.core.app_root > reagent2)

This is my code

(def react-navigation (js/require "react-navigation"))
(def StackNavigator (aget react-navigation "StackNavigator"))

(defn Home
  []
  [text "Hello Navigator"])

(defn SimpleApp
  []
  (StackNavigator
    (clj->js {:Home {:screen (r/create-class {:reagent-render (Home)})}})))

(defn init []
  (dispatch-sync [:initialize-db])
  (.registerComponent rn/app-registry "main" #(r/reactify-component app-root)))

This is my app-root

(defn app-root []
  (SimpleApp)); -- error
  ;(r/create-class {:reagent-render SimpleApp}); error
  ;(r/as-element (SimpleApp)); -- error
  ;(r/adapt-react-class SimpleApp)); --  error
2

There are 2 answers

0
xfyre On

The trick is to convert React Native components to Reagent components and back where needed. In the following example definitions of login-screen and main-screen are omitted, they're just regular Reagent components.

(def react-navigation (js/require "react-navigation"))
(def stack-navigator (.-createStackNavigator react-navigation))
(def switch-navigator (.-createSwitchNavigator react-navigation))
; ...
; ...
; ...
(defn application-nav-stack []
  (stack-navigator (clj->js { "MainApp" (r/reactify-component main-screen) })))

(defn authentication-nav-stack []
  (stack-navigator (clj->js { "Login" (r/reactify-component login-screen) })))

(defn app-navigation-switch []
  (switch-navigator
    (clj->js { :Auth (authentication-nav-stack)  :MainApp (application-nav-stack)  })
    (clj->js { :initialRouteName :Auth } )))

(defn app-root []
  [ (r/adapt-react-class (app-navigation-switch)) ] )

(defn init []
  (dispatch-sync [:initialize-db])
  (.registerComponent app-registry "MyApp" #(r/reactify-component app-root)))

Whenever you pass a Reagent component to ReactNavigation function you need to use reactify-component to convert it to the native JS form; whenever you need to use ReactNavigation component as a part of Reagent component, you need to use adapt-react-class to convert it back.

0
Oleg Kilimnik On
  (ns same.app
  (:require [reagent.core :as r]
            [same.ui :as ui]
            [same.util :as u]
            [same.screens.auth :refer [AuthScreen]]
          ;  [same.screens.reg :refer [RegScreen]]
         ;  [same.screens.resend :refer [ResendScreen]]
            [same.screens.splash :refer [SplashScreen]]
           ; [same.screens.drawer :refer [Drawer]]
            [same.screens.presentation :refer [Presentation]]))

(def routes #js {;:Drawer #js {:screen (r/reactify-component Drawer)}
                 :AuthScreen #js {:screen (r/reactify-component AuthScreen)}
                 ;:RegScreen #js {:screen (r/reactify-component RegScreen)}
                 ;:ResendScreen #js {:screen (r/reactify-component ResendScreen)}
                 :Presentation #js {:screen (r/reactify-component Presentation)}
                 :Splash #js {:screen (r/reactify-component SplashScreen)}})

(def Routing (ui/StackNavigator.
               routes
               #js {:initialRouteName "Splash"
                    :headerMode "none"
                    :mode "modal"}))

(def routing (r/adapt-react-class Routing))

(defn AppNavigator []
  (fn []
    [routing]))

and android.core:

(ns same.android.core
  (:require [reagent.core :as r :refer [atom]]
            [re-frame.core :refer [dispatch-sync]]
            [same.ui :as ui]
            [same.events]
            [same.subs]
            [same.app :refer [AppNavigator]]))

(aset js/console "disableYellowBox" true)

(defn app-root []
  (fn []
    [AppNavigator]))

(defn init []
  (dispatch-sync [:initialize-db])
  (.registerComponent ui/app-registry "Same" #(r/reactify-component app-root)))