Fork me on GitHub
#cljsrn
<
2020-01-14
>
Eric Ihli12:01:31

Trying to understand what's going on behind the scenes so I can maybe make my workflow a little better. I'm working with RN and shadow-cljs in a CIDER repl. I make a change to my code, the change causes my app to blow up during render so that I must hit r,r to reload and get it working again. After reloading, my REPL loses connection to the JS environment and any command I type in to the REPL gives me a REPL command timed out. message. I have found two ways to get the REPL re-connected. I can either type :cljs/quit -> (in-ns 'shadow.user) -> (shadow/repl-runtime-clear) -> (shadow/repl :app) and then I'm back in business. That was annoying. Or, I can close the application from the emulator and then re-open it from the list of apps. Why would closing and re-opening the app work to get the REPL re-connected but doing a r,r reload doesn't work? Is this the typical workflow that everyone uses for working with RN/CLJS? It seems tedious.

thheller12:01:52

@ericihli its a bug in react-native in that it doesn't disconnect websockets when reloading the app

thheller12:01:27

so shadow-cljs thinks the "old" app is still running and tries talking to it (but it never replies)

thheller12:01:28

I opened an issue on the RN repo but it was closed due do inactivity for a year or so. nobody cared I guess.

thheller12:01:52

I don't do RN development myself so I didn't follow up on it

danielneal12:01:49

The RN issues list is a wild and lawless place

parrot 4
😂 4
Eric Ihli16:01:53

I think I may have just found a solution. Seems to solve my problem in a way I'm happy with. Anyone see any gotchas?

(defn make-reloader
  [component]
  (let [component-ref (r/atom component)
        wrapper (r/create-class 
                 {:render (fn []
                            (let [component @component-ref]
                              (if (fn? component)
                                (component)
                                component)))
                  
                  :component-did-mount
                  (fn []
                    (.addEventListener
                     rn/AppState
                     "change"
                     (fn [state]
                       (cond
                         (= state "background")
                         (.close @shadow-rn/socket-ref)

                         (and (= state "active")
                              (nil? @shadow-rn/socket-ref))
                         (shadow-rn/ws-connect)))))})]
    (rn/AppRegistry.registerComponent "Ezmonic" (fn [] wrapper))
    (fn [comp]
      (reset! component-ref comp))))
http://facebook.github.io/react-native/docs/appstate.html

dotemacs16:01:31

When do you use this @ericihli , when the app “times out” when developing Android? Thanks

Eric Ihli16:01:52

It's my root component. If you put prints in component-did-mount you'll see the state changes happen on reload.

(defonce reload (make-reloader views/app-container))

(defn ^:dev/after-load start []
  (reload views/app-container))

(defn ^:export init []
  (start))