{"action":"closed","issue":{"url":"https://api.github.com/repos/lhorie/mithril.js/issues/442","labels_url":"https://api.github.com/repos/lhorie/mithril.js/issues/442/labels{/name}","comments_url":"https://api.github.com/repos/lhorie/mithril.js/issues/442/comments","events_url":"https://api.github.com/repos/lhorie/mithril.js/issues/442/events","html_url":"https://github.com/lhorie/mithril.js/issues/442","id":56585427,"number":442,"title":"Enhance Redraw Strategy to be Granular","user":{"login":"lawrence-dol","id":8662551,"avatar_url":"https://avatars.githubusercontent.com/u/8662551?v=3","gravatar_id":"","url":"https://api.github.com/users/lawrence-dol","html_url":"https://github.com/lawrence-dol","followers_url":"https://api.github.com/users/lawrence-dol/followers","following_url":"https://api.github.com/users/lawrence-dol/following{/other_user}","gists_url":"https://api.github.com/users/lawrence-dol/gists{/gist_id}","starred_url":"https://api.github.com/users/lawrence-dol/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lawrence-dol/subscriptions","organizations_url":"https://api.github.com/users/lawrence-dol/orgs","repos_url":"https://api.github.com/users/lawrence-dol/repos","events_url":"https://api.github.com/users/lawrence-dol/events{/privacy}","received_events_url":"https://api.github.com/users/lawrence-dol/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":null,"milestone":null,"comments":7,"created_at":"2015-02-04T20:51:01Z","updated_at":"2015-02-10T04:31:16Z","closed_at":"2015-02-10T04:31:16Z","body":"I've argued previously that `m.redraw.strategy` as implemented is a fundamentally broken concept, being a global flag for a non-global state.\r\n\r\nI think that the issues encountered with the strategy in [How to mitigate infinite redraw loop] (https://github.com/lhorie/mithril.js/issues/439) and [problems in submodules] (https://groups.google.com/d/msg/mithriljs/-G5MxbBVRcI/r9lTIwTBY88J) are further evidence of that. \r\n\r\nIt comes down to my argument that while any one part of a complex system can say \"the model **has** changed and the view **must be** updated\", no one part can say \"the model **has not** changed and the view **need not** be updated\" (where, of course, the model means any part, data or state). But the the redraw strategy flag is a global representation of the latter and as a result the last call to `m.redraw.strategy()` \"wins\".\r\n\r\nI think it could work compatibly if at the completion of each logical unit of work which could affect the model (e.g. an event, subcomponent instantiation, etc) the value of `m.redraw.strategy` were reset after being applied to a single internal flag which indicated a view update is required. After rendering a view the internal flag is cleared to \"none\"; after completing a unit of work the flag is set if the strategy is not \"none\" and the *strategy* is reset to \"diff\". Setting would be something along the lines of:\r\n\r\n    updateView=(updateView==\"all\" || strategy==\"all\" ? \"all\" : (updateView==\"diff\" || strategy==\"diff\" ? \"diff\" : \"none\"));\r\n\r\nThus the default for an action which does not set the strategy is still \"diff\", but if all actions set \"none\" the end-result is \"none\" and if any action sets other than \"none\" the most extensive strategy wins. In this way if any action sets \"all\" the view is entirely recreated; otherwise if any action sets \"diff\" (the default) the entire view is differentially recreated; otherwise no action required the view be updated.\r\n\r\nThis does imply a strict hierarchy between redraw strategies of all -> diff -> none. \r\n\r\nThe remaining tricks would be to correctly determine what things constitute a separate unit of action and actually trigger the view rendering when the UI loop is over. I've done the latter like this, which would be invoked every time the internal flag was set, resulting in a redraw on the next UI loop:\r\n\r\n    function redrawRqd() {\r\n        if(!MithrilUtil.redrawPending) {\r\n            MithrilUtil.redrawPending=true;\r\n            setTimeout(function() {\r\n                m.redraw();\r\n                MithrilUtil.redrawPending=false;\r\n                },20);                                                                                  // 1000/20 = 50 fps\r\n            }\r\n        }\r\n"}}