Automatic Redraws vs Manual m.redraw() for High-Frequency State Changes in Mithril.js
0 reputation · 17 Jun 2020, 05:05 UTC
0 reputation · 17 Jun 2020, 05:05 UTC
In Mithril.js 2.x, every event handler normally triggers a global redraw through the virtual DOM diff. For components receiving high-frequency updates—such as a timer, sensor stream, or rapid input—this automatic synchronization keeps state and view consistent without extra bookkeeping, but it forces the entire application tree to reconcile on each change. The documented alternative is to return false from the handler, disable that automatic trigger, and call m.redraw() only when the view should update.
The trade-off is between the productivity of automatic synchronization and the execution efficiency of manual control. Because Mithril does not provide a built-in granular component-level redraw, opting out means the developer must decide exactly when a full redraw is necessary. If m.redraw() is omitted after a state mutation, the UI can remain stale; if it is called too broadly, the performance benefit disappears. Current documentation should be checked to confirm whether newer versions have changed this behavior.
Which approach is more appropriate when a single component updates dozens of times per second but sibling components must not re-render? How can missed m.redraw() calls be detected without manually auditing every state mutation? Is there a documented pattern for scoping manual redraws to a subtree rather than the whole application?
35275 reputation · 17 Jun 2020, 09:21 UTC
For a component updating dozens of times per second while siblings must stay idle, the appropriate approach is to isolate that component in its own root DOM node and set m.redraw.strategy('none'), then call m.redraw() manually after each state mutation. Mithril does not provide a built-in subtree redraw API, so scoping manual redraws to a subtree means giving that subtree its own mount root.
In Mithril 2.x, event handlers trigger a global redraw by default. When a timer or sensor stream fires rapidly, every tick reconciles the entire virtual DOM tree, including siblings that have not changed. Returning false from the handler suppresses the automatic redraw for that event, but without a separate root it does not limit the scope of a subsequent manual m.redraw().
The documented pattern for isolation is to mount the high-frequency component in a dedicated element:
// Main app root
m.mount(document.getElementById('main'), App)
// Isolated high-frequency component
m.mount(document.getElementById('sensor'), SensorPanel)
With m.redraw.strategy('none') set globally, each m.redraw() call only walks the virtual DOM tree of the root that owns the changed state, leaving sibling roots untouched. If the high-frequency component shares a root with its siblings, a manual m.redraw() still triggers a full-tree reconciliation and the performance benefit disappears.
Mithril does not ship a lint rule or runtime warning for forgotten m.redraw() calls. Two practical detection strategies are:
m.redraw.strategy('sync') and mutate state without calling m.redraw(). If the view remains unchanged, the mutation is missing its redraw.'none' but no m.redraw() occurs within the same animation frame.Confirmed for Mithril 2.x: event handlers trigger a global redraw unless they return false, and m.redraw() performs a full-tree reconciliation from the root that owns the changed state. The subtree-isolation pattern—mounting the high-frequency component in its own DOM node—is the established workaround because Mithril lacks a native subtree redraw API. Because the research brief flags that current documentation should be re-checked, confirm the exact m.redraw.strategy values and the return false contract against the latest Mithril.js release before deploying.
One diagnostic detail that changes the recommendation: Does the high-frequency component currently share a root DOM element with the siblings that must not re-render? If it does, restructuring the mount hierarchy is a prerequisite; if it already has its own root, the strategy switch alone is sufficient.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.