React apps now run on the desktop with Electron. They also run on the desktop with react-native-desktop, or proton-native. In this simple post, I’ll share my (very small!) experience with proton-native:
First, you need Shadow-CLJS. Because of the npm integration, you can literally just:
npm install proton-native react react-dom create-react-class
And then add [reagent "0.8.1"] to dependencies on shadow-cljs.edn file. Then, configure a :node-script target and start to build things. This means that your shadow-cljs.edn file will be:
{:source-paths ["src" "test"]
:dependencies [[reagent "0.8.1"]]
:builds {:desktop {:target :node-script
:main demo.app/init
:output-to "target/index.js"}}}
Now, you have to create the src/demo/app.cljs with the following contents:
(ns demo.app
(:require [reagent.core :as r]
["react" :as React]
["proton-native" :refer [render Window App Button Box]]))
(defonce state (r/atom 0))
(defn- win []
[:> Box
[:> Button {:stretchy false :onClick #(prn :Bye)}
"Click Lol!!"]
[:> Button {:stretchy false :onClick #(swap! state inc)}
@state]])
(defonce primary-view (r/atom win))
(defn example []
[:> App
[:> Window {:title "Example" :size {:w 300 :h 300} :menuBar false}
(r/as-element [@primary-view])]])
(defn init [ & args]
(render (r/as-element [example])))
(defn ^:dev/after-load reload []
(reset! primary-view win))
There is something that we need to be aware: if you look at example implementation, you’ll see that it derefs the primary-view reagent atom. By doing it, we get auto-reload for free, and its even more impressive considering that it is not supported by proton-native!.