Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

components #486

Closed
9 tasks
yoshuawuyts opened this issue Apr 27, 2017 · 6 comments
Closed
9 tasks

components #486

yoshuawuyts opened this issue Apr 27, 2017 · 6 comments

Comments

@yoshuawuyts
Copy link
Member

So @Karissa asked in https://github.com/datproject/datproject.org/issues/511 what the status is on a certain component, and I linked to like 5 different things. I feel I've got a pretty good grasp of the status of components in choo, but that information is not written down anywhere right now. So this is a tracking issue to figure out where our components are at.

Building components

When I first wrote about the ideas of choo v5, I also mentioned components. We didn't end up shipping components in the final release. This was because it turned out all the primitives for components can be built on top of choo, so by documenting the patterns needed, we can have them live as separate modules instead.

At their core, components are stateful DOM nodes that are not affected by the diffing algorithm. They manage their own lifecycle, and fire internal events when they're mounted, unmounted or receive new data. This makes them ideal to wrap stateful third party code, like the leaflet map framework.

In order to achieve stateful nodes, we must make sure that certain parts of the DOM tree are not diffed by nanomorph. We can do this by setting .isSameNode() on a node. This must be done conditionally, however, because at a first render we must pass a DOM tree. To detect when nodes are added and removed from the DOM we use on-load. Because wiring all these bits up together can be tricky, and prone to error, we created nanocomponent.

nanocomponent is the core of our component abstraction. It's just a convention turned into code. It exposes a prototypical API, which might prove to be a bit unwieldy if you're writing application code. So for applications we've created microcomponent. It has a whole bunch of conventions around state management, logging, tracing, and determining if elements should be updated. If you're curious how to write your own nanocomponent-based elements, I think the microcomponent API should give you a good idea of how to shape it (e.g. never expose a prototype API for application-level code).

Core modules

  • nanocomponent is the core abstraction for our components. It's a convenience wrapper around the patterns nanomorph requires to have stateful nodes, and uses on-load under the hood. It exposes a prototypical API. This is a module-level component; you should generally only use this if you're creating modules to put on npm and not in applications.
  • cache-element caches an element, forever. This is ideal for parts of the app that never change (e.g. headers, footers, inner elements, etc.)
  • microcomponent is a small wrapper around nanocomponent. It exposes an API that's quite similar to React's component API. But we also include tracing and logging, which makes it very debuggable. This is an application-level component; you should generally only use this if you're writing applications, and not use it to to create npm modules.
  • cache-component by @bcomnes - a different take on microcomponent. This is not sure yet, but I think there's a fair chance the two modules may converge in the future (or find a slightly different niche, too soon to tell)

Issues

ecosystem

And there's probably other elements that can be done: tabs, dropdown menus, slide-in panels, notification bubbles. The works. It'd be cool if people that are interested would start building those out too!

Wrapping up

And that's it - I think this captures the current state of components in choo. I hope it's been useful, and if you build something cool, have questions or want to help out on any of this - we'd love to hear from you! Cheers! ✨

@bcomnes
Copy link
Collaborator

bcomnes commented Apr 27, 2017

Nice writeup

@YerkoPalma
Copy link
Member

I like the nanocomponent idea, but after reading this, it doen't sound like components are a part of choo. I mean, they can be used with choo, but they are not made for choo, also you could use (maybe) another component library with choo.
So, when I think about choo components I imagine a plugin or library that extend nanocomponent and allow to use components in choo like this

var html = require('choo/html')
var choo = require('choo')
var components = require('choo-components')

var app = choo()
app.use(components(require('list-component'), require('form-component')))
app.route('/', mainView)
app.mount('body')

function mainView (state, emit) {
  return html`
    <body>
      <h1>count is ${state.count}</h1>
      <FormComponent path=${state.path}>
        <List source=${state.data}></List>
      </FormComponent>
    </body>
  `
}

I don't know if that make sense, but thats the way it feels natural for me to use components. The registration method was the first one I came up with haha.

@yoshuawuyts
Copy link
Member Author

yoshuawuyts commented May 9, 2017 via email

@timwis
Copy link
Member

timwis commented May 21, 2017

Great summary. Has anyone played around with ways to initialise the components? You have to use new and cache the instance for later renders. It becomes very difficult with lists.

@bcomnes
Copy link
Collaborator

bcomnes commented May 22, 2017

I've only component-ized the entire list. I imagine the only way to do it with list items, is to track instances in an array, and manage their lifecycle in the array.

@YerkoPalma
Copy link
Member

Components are now availaible in choo, I guess is safe to close this, reopen otherwise.

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

No branches or pull requests

4 participants