Yesterday I made a post outlining a few things you can do to ensure your Reagent code is optimized. It seems that it was barely scratching the surface so I decided to make a part 2!

Avoid Overuse of Deref in Render Functions

Frequent dereferencing inside render functions can trigger unnecessary re-renders. Minimize derefs or lift them out of the render body where possible.

(defn counter [count]
  (let [val @count]
    [:div
     [:span "Count: " val]
     [:button {:on-click #(swap! count inc)} "Increment"]]))
Why this helps:

Dereferencing in multiple places in the render function could lead to redundant updates.

Use shouldComponentUpdate with r/create-class

For components with static or rarely changing props, you can prevent re-renders by implementing a shouldComponentUpdate method using create-class.

(defn static-component []
  (reagent/create-class
    {:reagent-render (fn [] [:div "I rarely update!"])
     :should-component-update (fn [_ _] false)}))
Why this helps:

This is especially useful for large components or components with expensive render logic.

Batch Updates with r/run!

Reagent automatically batches DOM updates, but for custom async updates, you can use run! to group state changes efficiently.

(defn batch-example []
  (let [state (reagent/atom 0)]
    (reagent/run! (reset! state 1) (reset! state 2))
    [:div "State: " @state]))
Why this helps:

Batching prevents intermediate states from triggering unnecessary renders.

Optimize Collections with key Props

When rendering lists, always provide a key prop to help Reagent identify which items changed, improving rendering efficiency.

(defn item-list [items]
  [:ul (for [item items]
         ^{:key (:id item)}
         [:li (:name item)])])
Why this helps:

Without a key, Reagent will re-render the entire list instead of reusing existing DOM nodes.

Avoid Over-Normalizing Small Apps

In simple apps, over-normalizing state (splitting every field into its own atom) can lead to complexity and unnecessary renders. Strike a balance between granularity and simplicity.

Instead of multiple atoms:

(def name (reagent/atom "Sam"))
(def age (reagent/atom 25))

Use a single atom for fields:

(def app-state (reagent/atom {:name "Sam" :age 25}))