Fork me on GitHub
#cljsrn
<
2023-06-03
>
pez16:06:14

I’m trying to get React Navigation to play with me. I get the navigation to work, but am a bit confused about how to stop shadow-cljs reload to not rerender the navigation stack. Right now if I navigate to the About screen and then rerender the root component (such as happens when I save the file) the Home screen gets rendered. The relevant code (I think):

(defn root []
  [:> rnn/NavigationContainer 
   [:> Stack.Navigator
    [:> Stack.Screen {:name "Home"
                      :component (fn [props] (r/as-element [home props]))
                      :options {:title "Home"}}]
    [:> Stack.Screen {:name "About"
                      :component (fn [props] (r/as-element [about props]))
                      :options {:title "About"}}]]])

(defn start
  {:dev/after-load true}
  []
  (expo-root/render-root (r/as-element [root])))

pez10:06:57

Turns out I can set the initial state of the navigation container. This branch of my example app now has navigation with smooth hot reload: https://github.com/PEZ/rn-rf-shadow/tree/pez/react-navigation Pasting the new root component code here, for easy reference:

(defn root []
  ;; The save and restore of the navigation root state is for development time bliss
  (r/with-let [!root-state (rf/subscribe [:navigation/root-state])
               save-root-state! (fn [^js state]
                                  (rf/dispatch [:navigation/set-root-state state]))
               add-listener! (fn [^js navigation-ref]
                               (when navigation-ref
                                 (.addListener navigation-ref "state" save-root-state!)))]
    [:> rnn/NavigationContainer {:ref add-listener!
                                 :initialState (when @!root-state (-> @!root-state .-data .-state))}
     [:> Stack.Navigator
      [:> Stack.Screen {:name "Home"
                        :component (fn [props] (r/as-element [home props]))
                        :options {:title "Example App"}}]
      [:> Stack.Screen {:name "About"
                        :component (fn [props] (r/as-element [about props]))
                        :options {:title "About"}}]]]))

(defn start
  {:dev/after-load true}
  []
  (expo-root/render-root (r/as-element [root])))

pez10:06:57

Turns out I can set the initial state of the navigation container. This branch of my example app now has navigation with smooth hot reload: https://github.com/PEZ/rn-rf-shadow/tree/pez/react-navigation Pasting the new root component code here, for easy reference:

(defn root []
  ;; The save and restore of the navigation root state is for development time bliss
  (r/with-let [!root-state (rf/subscribe [:navigation/root-state])
               save-root-state! (fn [^js state]
                                  (rf/dispatch [:navigation/set-root-state state]))
               add-listener! (fn [^js navigation-ref]
                               (when navigation-ref
                                 (.addListener navigation-ref "state" save-root-state!)))]
    [:> rnn/NavigationContainer {:ref add-listener!
                                 :initialState (when @!root-state (-> @!root-state .-data .-state))}
     [:> Stack.Navigator
      [:> Stack.Screen {:name "Home"
                        :component (fn [props] (r/as-element [home props]))
                        :options {:title "Example App"}}]
      [:> Stack.Screen {:name "About"
                        :component (fn [props] (r/as-element [about props]))
                        :options {:title "About"}}]]]))

(defn start
  {:dev/after-load true}
  []
  (expo-root/render-root (r/as-element [root])))