Instantly share code, notes, and snippets.

Embed
What would you like to do?
Work in progress: proposal for view attributes as a core mechanism in Mithril

Precedent: render props (or, view attributes)

I've been toying the idea of 'view attributes' for a while, but over the past year they've taken off in the popular domain of React as 'render props'.

A component written to make use of view attributes is a 'view component' inasmuch as it doesn't have an opinion on downstream virtual DOM, but performs a useful function in the context of virtual DOM (whether that be transforming other attribute input, querying DOM or external references, providing state), which can be exposed via the view attribute provided to it.

Here's a sample of view components with associated demos.

The React community has already proved the far-reaching value of this concept to the point where the pattern is part of the official documentation, ahead of 'integrating with other libraries'. React Router famously uses the pattern to avoid hard-baking isolated downstream concerns into a monolithic static route map definition. React Motion uses it to abstract the generic arithmetic concerns of animation over time and how this relates to lifecycle to produce an animation component that's completely agnostic about the structure or properties being animated.

The general principle of view-as-an-attribute is to provide a mechanism for separating 'pure' view concerns from modelling concerns that nonetheless ties into the declarative virtual DOM dialect in a way that's capable of leveraging the power of attributes, state & lifecycle.

Proposal: enable view-as-an-attribute in Mithril core

As demonstrated, view components can be implemented as a pattern in Mithril today. The general pattern involves a component with one or more lifecycle methods which assign properties to state, with the salient properties being fed to the view. A minimal straw man would look like this:

const Double = {
  view : ({attrs: {view, value}) =>
    view(value * 2)
}

// ...

m(Double, {
  value: 4,
  view: double =>
    m('h2', double)
}

As an important aside, a view component that has no use for lifecycle hooks is an anti-pattern: view components should indicate that virtual DOM APIs are necessary. React in practice is plagued by misuse of React API entities to fulfil functionality which is utterly agnostic to virtual DOM considerations and could be expressed with much simpler pure functions. The above serves simply as an example of the view definition and call site in practice without external ambiguities.


TBC

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment