BS"D
I am not the only one using mithril. I am not every day on github, but I'm seeing a repeating pattern of fixing what isn't broken.
I am seeing changes to the framework to the router, that before was solid, now the community is saying don't rely on it but use a third party.
A code base doesn't need to change every week or month, and I am seeing lots of changes to things that are not broken or just because we can - or because it's the way React does it... (If we wanted react we wouldn't be here)
It's probably good to create some policy for admitting changes. In general the foundation of the framework is based on keep it simple and bare, and if you need extraordinary additions - use a plugin. A vanilla, fast, and simple framework.
Also, there are times that bugs come up, and unfortunately mithril versions are no longer compatible because features are added on right and on left for single requests that nobody else needs and a scenario that can be tailored to that specific case, and not the framework.
I think it's healthy that most answers are how to make it work in mithril. But the trend has changed to let's change mithril to work for your question.
Mithril is an awesome framework, but if we turn it into Reactthril or vuethril, then it's not mithril anymore.
My immense gratitude to all contributors toward making Mithril better!
@ycadaner-merkos302 Many of those changes making it React-like were done by Leo Horie himself, the original creator of Mithril. And you can rest assured you're not alone in feeling Mithril is getting too React-like. 馃檪
A code base doesn't need to change every week or month, and I am seeing lots of changes to things that are not broken or just because we can - or because it's the way React does it... (If we wanted react we wouldn't be here)
Some of the changes were specifically because the previous design itself was broken. m.route.link → m.route.Link was one concrete example, where I switched to a more React-like API simply because too many people were running into paper cuts having to do oncreate: m.route.link, onupdate: m.route.link if that link ever changed. I did that unilaterally because 1. it was a long-standing feature request, 2. it came up semi-regularly with users, and 3. it was a common source of gotchas. We've also made changes to other features in the past for similar reasons, like fixing m.redraw() to always be async and creating a separate m.redraw.sync() for sync redraws.
Also, Mithril doesn't release updates that quickly - we move fairly slow. Compare that to React, which in the last four five updates:
React.lazy, React.memo, static contextType. All three decent-sized features.React.lazy.act() support, a lot of new deprecations.Here's the last 5 releases for Mithril:
Couple critically broken, unpublished releases excluded. I also excluded all the other release candidates for brevity.
We just had a major release, so that skews things a lot, but we do still move much slower than React does. We also try to be much smaller in code size, as that does have a major impact on startup, and this necessarily means being more judicious on what we do add.
I think it's healthy that most answers are how to make it work in mithril. But the trend has changed to let's change mithril to work for your question.
Mithril has always been very oriented towards getting out of the developer's way. My thing is that I've been trying to take that even further, by altering Mithril to continue getting out of people's ways. And in some cases, it means making it more intuitive so you aren't having to think as hard when using it. Ideally, you shouldn't have to fight the framework at all.
You're probably just looking at the feature requests and some of the early v3 investigation.
m.route.SKIP eliminates the need for onmatch. It also has more general uses, of course. When you combine these two, that's what opens up the possibility of #2506, which is pretty unlike React Router in its hybrid static/dynamic design. And trust me when I say this: our current router design is broken. I have to field far too many questions on how to do specific things, and even basic things like page layouts are unnecessarily complicated.{subtree: "retain"} (likely in the form of m.RETAIN) for v3, and if we combine that with this, onbeforeupdate immediately becomes redundant with view, and oncreate + onupdate can be merged into a single lifecycle hook if you pass null for the previous attributes on first call.In much of this, I've been noticing survivorship bias at work, with occasional stories of why people stop using Mithril and why people chose to skip Mithril (usually in favor of React), despite being impressed by the framework. Their reasons are as valuable as the regular complaints I normally get with various aspects of Mithril, and are often far more informative of where the issues truly lie. Some things do truly need fixed, but the issues at play are much more in-depth and multi-faceted, and so I have to address them in multiple spots at once. Sometimes, it's as simple as adding a small feature, like m.route.SKIP. Sometimes, it's a small design tweak, like splitting v1's sometimes-sync m.redraw() into the more consistent m.redraw() and m.redraw.sync(). Sometimes, it requires completely overhauling the API, like m("a", {...attrs, oncreate: m.route.link(opts), onupdate: m.route.link(opts)}, ...) → m(m.route.Link, {...opts, ...attrs}, ...).
Also, about half of these issues I linked to here have a fairly long history of discussion in our Gitter channel, here in our issue tracker, and sometimes elsewhere. Very little of this is even new.
I am seeing changes to the framework to the router, that before was solid, now the community is saying don't rely on it but use a third party.
That's not something I've been hearing. Most of those recommendations are people wanting stuff out of a router that not even the most massive of frameworks like Rails, Ember, and Angular offer out of the box, and I'm adding literally the bare minimum (like m.route.SKIP, which is also separately useful for other reasons) to un-block them. But this is for a very small minority coming with very advanced issues.
Mithril is an awesome framework, but if we turn it into Reactthril or vuethril, then it's not mithril anymore.
Trust me: none of us active or former developers want to turn Mithril into anything React-like. Leo was heavily inspired by React in his v1 rewrite a few years ago, but we've been slowly undoing that ourselves, with even some of the initial rewrite becoming less React-like before it first went stable. I've personally been working on a redesign that captures the simplicity and power of Mithril without nearly the drawbacks of the design hacks that v0.2 suffered with extensively (like m.startComputation()/m.endComputation()) or the unnecessary OO-isms that plague v1 and v2 (like onbeforeupdate and m.request's type parameter). So don't worry. 馃槈
I do want to point out that some things one might think are React-isms aren't even React-specific and are just part of the immediate mode tree-patching UI paradigm that virtual DOM libraries and frameworks inhabit. And some are more general than even that. For example:
m.redraw() and React's this.setState(newState)) is innate to all UI frameworks.oncreate/onupdate in Mithril and componentDidMount/componentDidUpdate in traditional React, but not always, like useEffect in React Hooks.React.memo, Elm in all cases), some make this explicit (shouldComponentUpdate in React, onbeforeupdate in Mithril v1/v2, {subtree: "retain"} vnode in Mithril v0.2).This is by no means complete (keys for one), but should hopefully give you a better idea of where things differ.
My immense gratitude to all contributors toward making Mithril better!
Many "thank you"s! Much appreciated! 馃檪
Most helpful comment
@ycadaner-merkos302 Many of those changes making it React-like were done by Leo Horie himself, the original creator of Mithril. And you can rest assured you're not alone in feeling Mithril is getting too React-like. 馃檪
Some of the changes were specifically because the previous design itself was broken.
m.route.link→m.route.Linkwas one concrete example, where I switched to a more React-like API simply because too many people were running into paper cuts having to dooncreate: m.route.link, onupdate: m.route.linkif that link ever changed. I did that unilaterally because 1. it was a long-standing feature request, 2. it came up semi-regularly with users, and 3. it was a common source of gotchas. We've also made changes to other features in the past for similar reasons, like fixingm.redraw()to always be async and creating a separatem.redraw.sync()for sync redraws.Also, Mithril doesn't release updates that quickly - we move fairly slow. Compare that to React, which in the last four five updates:
React.lazy,React.memo,static contextType. All three decent-sized features.React.lazy.act()support, a lot of new deprecations.Here's the last 5 releases for Mithril:
Couple critically broken, unpublished releases excluded. I also excluded all the other release candidates for brevity.
We just had a major release, so that skews things a lot, but we do still move much slower than React does. We also try to be much smaller in code size, as that does have a major impact on startup, and this necessarily means being more judicious on what we do add.
Mithril has always been very oriented towards getting out of the developer's way. My thing is that I've been trying to take that even further, by altering Mithril to continue getting out of people's ways. And in some cases, it means making it more intuitive so you aren't having to think as hard when using it. Ideally, you shouldn't have to fight the framework at all.
You're probably just looking at the feature requests and some of the early v3 investigation.
m.route.SKIPeliminates the need foronmatch. It also has more general uses, of course. When you combine these two, that's what opens up the possibility of #2506, which is pretty unlike React Router in its hybrid static/dynamic design. And trust me when I say this: our current router design is broken. I have to field far too many questions on how to do specific things, and even basic things like page layouts are unnecessarily complicated.{subtree: "retain"}(likely in the form ofm.RETAIN) for v3, and if we combine that with this,onbeforeupdateimmediately becomes redundant withview, andoncreate+onupdatecan be merged into a single lifecycle hook if you passnullfor the previous attributes on first call.In much of this, I've been noticing survivorship bias at work, with occasional stories of why people stop using Mithril and why people chose to skip Mithril (usually in favor of React), despite being impressed by the framework. Their reasons are as valuable as the regular complaints I normally get with various aspects of Mithril, and are often far more informative of where the issues truly lie. Some things do truly need fixed, but the issues at play are much more in-depth and multi-faceted, and so I have to address them in multiple spots at once. Sometimes, it's as simple as adding a small feature, like
m.route.SKIP. Sometimes, it's a small design tweak, like splitting v1's sometimes-syncm.redraw()into the more consistentm.redraw()andm.redraw.sync(). Sometimes, it requires completely overhauling the API, likem("a", {...attrs, oncreate: m.route.link(opts), onupdate: m.route.link(opts)}, ...)→m(m.route.Link, {...opts, ...attrs}, ...).Also, about half of these issues I linked to here have a fairly long history of discussion in our Gitter channel, here in our issue tracker, and sometimes elsewhere. Very little of this is even new.
That's not something I've been hearing. Most of those recommendations are people wanting stuff out of a router that not even the most massive of frameworks like Rails, Ember, and Angular offer out of the box, and I'm adding literally the bare minimum (like
m.route.SKIP, which is also separately useful for other reasons) to un-block them. But this is for a very small minority coming with very advanced issues.Trust me: none of us active or former developers want to turn Mithril into anything React-like. Leo was heavily inspired by React in his v1 rewrite a few years ago, but we've been slowly undoing that ourselves, with even some of the initial rewrite becoming less React-like before it first went stable. I've personally been working on a redesign that captures the simplicity and power of Mithril without nearly the drawbacks of the design hacks that v0.2 suffered with extensively (like
m.startComputation()/m.endComputation()) or the unnecessary OO-isms that plague v1 and v2 (likeonbeforeupdateandm.request'stypeparameter). So don't worry. 馃槈I do want to point out that some things one might think are React-isms aren't even React-specific and are just part of the immediate mode tree-patching UI paradigm that virtual DOM libraries and frameworks inhabit. And some are more general than even that. For example:
m.redraw()and React'sthis.setState(newState)) is innate to all UI frameworks.oncreate/onupdatein Mithril andcomponentDidMount/componentDidUpdatein traditional React, but not always, likeuseEffectin React Hooks.React.memo, Elm in all cases), some make this explicit (shouldComponentUpdatein React,onbeforeupdatein Mithril v1/v2,{subtree: "retain"}vnode in Mithril v0.2).This is by no means complete (keys for one), but should hopefully give you a better idea of where things differ.
Many "thank you"s! Much appreciated! 馃檪