mithril.js
mithril.js copied to clipboard
Add support for an optional removal callback function returned from oncreate
Recent discussions on possible future design directions for Mithril have suggested there is a desire to reduce the number of lifecycle hooks. From those discussions arose a suggestion to provide the equivalent of the current onremove hook by returning a function from oncreate.
This could be added to the current V2 API in a non-breaking way, and could provide a nicer API for setup/teardown for certain use cases, generally revolving around direct DOM access. For example, to set up a component that automatically resizes a canvas element, one must currently write something like:
function MyComponent() {
let canvas
function resize() {
const rc = canvas.getBoundingClientRect()
canvas.width = rc.width
canvas.height = rc.height
}
return {
oncreate: ({dom}) => {
canvas = dom
window.addEventListener('resize', resize)
},
onremove: () => {
window.removeEventListener('resize', resize)
},
view: () => m('canvas')
}
}
3rd party lib integration is often similar:
function ThirdPartyWrapper() {
let foo
return {
oncreate: ({dom}) => {
foo = Foo(dom)
},
onremove: () => {
foo.dispose()
},
view: () => m('div')
}
}
With a callback returned from oncreate, the above examples could be simplified to:
const MyComponent = {
oncreate: ({dom}) => {
function resize() {
const rc = dom.getBoundingClientRect()
dom.width = rc.width
dom.height = rc.height
}
window.addEventListener('resize', resize)
return () => {
window.removeEventListener('resize', resize)
}
},
view: () => m('canvas')
}
and:
const ThirdPartyWrapper = {
oncreate: ({dom}) => {
const foo = Foo(dom)
return () => {foo.dispose()}
},
view: () => m('div')
}
Stateful components are no longer needed simply to persist these stateful items that need cleanup.
There are of course other cases where stateful components will still be needed. And the onremove hook should of course continue to be supported. In cases where a function is returned from oncreate and a onremove hook exists, I would think onremove should be called last.
This could be added to the current V2 API in a non-breaking way, and could provide a nicer API for setup/teardown for certain use cases, generally revolving around direct DOM access.
I sympathize with the concept, but I'm not a fan of duplicating functionality in general. So I'd need something a lot more compelling than even this to want to add it to v2.
I will state such a change is very, very likely for v3, though.