3

Figwheel displays the code bellow just fine. But I have to refresh the page to see any changes. What has to change for Figwheel to show changes? Is there a command to force redraw, without losing the application state?

BTW: Chrome has Disable Cache true and the CLJS icon appears when the file is saved.

(defn simple-example []
  [ui/mui-theme-provider {:mui-theme (get-mui-theme
                                       {:palette {:text-color (color :blue800)}})}
   [:div
    [ui/app-bar {:title                 "Hi all"
                 :icon-class-name-right "muidocs-icon-navigation-expand-more"}]
    [ui/paper
     [:div
      [ui/tabs
       [ui/tab {:label "Menu" :value "0"}
        [:div "Hello world"]]]]]]]))

(defn ^:export run []
  (render [simple-example]
          (js/document.getElementById "app")))) 
dilvan
  • 2,109
  • 2
  • 20
  • 32
  • Do you get the "cljs-icon" popup after your writes each time? So is figwheel not loading your changes or have the changes not appearant effect? – cfrick Sep 19 '17 at 10:51

2 Answers2

4

From the docs:

Setting :figwheel true or :figwheel { :on-jsload "example.core/reload-hook" } will automagically insert the figwheel client code into your application. If you supply :on-jsload the name of a function, that function will be called after new code gets reloaded.

An example reload hook plus configuration for Reagent:

(ns your-namespace.core
  (:require [reagent.core :as r]))


(defn render [view]
  (let [node (.getElementById js/document "app")]
    (r/render-component view node)))


(defn rerender []
  (let [node (.getElementById js/document "app")]
    (r/unmount-component-at-node node)
    (render [:div "Reloading"]))


(defn ^:export reload []
  (rerender))

And then in your project.clj:

:cljsbuild {:builds {:dev {:source-paths ["src"] 
                           :figwheel     {:on-jsload "your-namespace.core/reload"}}}

/edit

Note that re-frame uses Reagent. In the case of re-frame I recommend starting with the re-frame-template. E.g.,

lein new re-frame your-project-name # options, e.g., +re-frisk +cider

This will give a default core.cljs as follows:

(defn dev-setup []
  (when config/debug?
    (enable-console-print!)
    (println "dev mode")))

(defn mount-root []
  (re-frame/clear-subscription-cache!)
  (reagent/render [views/main-panel]
                  (.getElementById js/document "app")))

(defn ^:export init []
  (re-frame/dispatch-sync [:initialize-db])
  (dev-setup)
  (mount-root))

The index.html has a node with id app and calls init. And the project.cljs specifies the on-jsload as follows:

:cljsbuild
{:builds
 [{:id           "dev"
   :source-paths ["src/cljs"]
   :figwheel     {:on-jsload "your-project-name.core/mount-root"}
#_(...)}}

This should absolutely update the page with the component changed. If it does not do what you want I might have misunderstood your question.

user2609980
  • 10,264
  • 15
  • 74
  • 143
  • I'm using [re-frame](https://github.com/Day8/re-frame). `:figwheel true` doesn't work. For `:figwheel { :on-jsload "example.core/reload-hook" }`, which function should I call (re-frame uses functions that return functions to create components)? – dilvan Sep 19 '17 at 16:44
  • @dilvan I updated the answer for re-frame. Let me know if it helps. – user2609980 Sep 19 '17 at 19:55
0

Reagent needs to be notified about state changes to re-render the affected components on the screen. Your code does not yet have any inner state that can be watched in order to decide if a re-render is required.

You can store your app state in reagent atoms. When you dedreference a reagent atom in a reagent component (that is the simple-example component in your case) an event listener is set up to the state atom so that any time it changes the component will be re-rendered.

Put the following just before the definition of simple-example:

(defonce counter (reagent.core/atom 0))
(swap! counter inc)

This creates a state called counter if it does not exist yet. It also immediately increases it so any already registered components will be refreshed.

Then put a @counter deref call anywhere inside the function body of simple-example. This way the initial call of the function installs the state change listeners.

Now any time you modify the code the namespace get reloaded and thus counter atom increases triggering the re-render of your component.

erdos
  • 3,135
  • 2
  • 16
  • 27
  • Thanks! But my problem remains: there will be code outside react components that needs to be changed. Isn't there a command to force the re-render of the screen (or of all components)? Maybe a REPL command? (BTW, I am using re-frame). – dilvan Sep 19 '17 at 10:49
  • Maybe put a `(deref state-atom)` inside the root component? – erdos Sep 19 '17 at 11:02
  • I'm using re-frame, how can I do that? BTW, is that the recommended way of doing that in figwheel? – dilvan Sep 19 '17 at 14:58