React native “经常看到”;REPL命令超时";在苹果酒中加入shadow cljs并与本机反应。必须重新启动emulator才能修复

React native “经常看到”;REPL命令超时";在苹果酒中加入shadow cljs并与本机反应。必须重新启动emulator才能修复,react-native,cider,shadow-cljs,React Native,Cider,Shadow Cljs,我正在使用一个基本的ReactNative应用程序,使用带有苹果酒和ShadowCLJS的Emacs。我可以非常一致地使用REPL进行开发,但是一旦我意外地保存了一个有语法错误的文件,我就失去了与REPL的通信。我键入的任何内容都会导致延迟,然后是“REPL命令超时”。我找到的唯一修复方法是使用npx react native run android重新启动模拟器。但是我失去了REPL中的所有状态。这可能是许多不同的事情 这可能与Metro(或Expo)提供的实时重新加载有关。在emulator

我正在使用一个基本的ReactNative应用程序,使用带有苹果酒和ShadowCLJS的Emacs。我可以非常一致地使用REPL进行开发,但是一旦我意外地保存了一个有语法错误的文件,我就失去了与REPL的通信。我键入的任何内容都会导致延迟,然后是“REPL命令超时”。我找到的唯一修复方法是使用
npx react native run android
重新启动模拟器。但是我失去了REPL中的所有状态。

这可能是许多不同的事情

这可能与Metro(或Expo)提供的实时重新加载有关。在emulator中按Ctrl-M(Mac上的Cmd-M)以打开关闭快速刷新的选项

如果在禁用快速刷新后仍然出现此错误,可能是因为ReactNative在重新加载时没有完全断开旧WebSocket的连接。下面是shadow cljs的创建者的评论

这是react native中的一个bug,它在重新加载应用程序时不会断开WebSocket,因此shadow cljs认为“旧”应用程序仍在运行,并尝试与它对话(但它从未回复)。我在RN repo上打开了一个问题,但由于一年左右的不活动而关闭。我想没人在乎

我找到了一个解决方法,可以使用ReactNative的AppState和shadow cljs dev命名空间中对websocket的引用

(defn on-app-state-change
  "Fixes issue with shadow-cljs repl losing connection to websocket.

  Put this in some root component's `component-did-mount`.
  https://stackoverflow.com/questions/40561073/websocket-not-closed-on-reload-appreact-native
  "
  [state]
  (cond
    (= state "background")
    (.close @shadow-rn/socket-ref)

    (and (= state "active")
         (nil? @shadow-rn/socket-ref))
    (shadow-rn/ws-connect)))

(defn make-reloader
  [component]
  (let [component-ref (r/atom component)]
    (letfn [(render []
              (let [component @component-ref]
                (if (fn? component)
                  (component)
                  component)))]
      (let [wrapper (r/create-class
                     {:render render
                      :component-did-mount
                      (fn []
                        (.addEventListener rn/AppState "change" on-app-state-change))

                      :component-will-unmount
                      (fn []
                        (.removeEventListener rn/AppState "change" on-app-state-change))})]

        (rn/AppRegistry.registerComponent "Ezmonic" (fn [] wrapper))
        (fn [comp]
          (reset! component-ref comp))))))