Search code examples
clojureclojurescriptfigwheel

Figwheel doesn't detect most changes in my code


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")))) 

Solution

  • 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.