lynaghk / cljs-react-perf

Performance experiments w/ CLJS React libraries and techniques.
40 stars 1 forks source link

What's the ideal way to invoke renders? #1

Open lynaghk opened 7 years ago

lynaghk commented 7 years ago

Consider a UI is derived entirely from a single state atom, where all updates go through the same codepath.

(def !state 
  (atom {}))

(rum/defc *app [app-state] ...)

(defn trigger! 
  [event]

  ;;update the application state
  (swap! !state update-state-fn event)

  ;;re-render the application state
  (.render js/ReactDOM 
           (*app trigger! @!state) 
           (.getElementById js/document "my-app")))

(trigger! :first-event-to-start-app)

One benefit of this rendering approach is that there is no distinction between the initial render and subsequent renders. No need to keep track of a React component, add watches to the state atom, or anything like that.

One downside is that if trigger! is called multiple times within a single frame, the React render function will run needlessly multiple times, when it really only needs to run once on the latest application state for a given frame.

Would it be better to do use requestAnimationFrame or mount the component once and then call rum/request-render? What would that look like?

Does it make a difference if you know that the *app template will or will not execute within the 16ms frame limit?

roman01la commented 7 years ago

Batching state updates via requestAnimationFrame is usually a way to go. I believe most React wrappers does so.

So basically it's better to control how you update state and let the library to handle an update on its own.