jorgebucaran / superfine

Absolutely minimal view layer for building web interfaces
https://git.io/super
MIT License
1.57k stars 78 forks source link

API update - mount() for mounting, patch() for patching #91

Closed estrattonbailey closed 6 years ago

estrattonbailey commented 6 years ago

As mentioned in #89, the current patch() API essentially does double duty: mounting to the DOM at a single node, and updating the tree as the application updates.

This PR aims to introduce a separate mount() function and updates the patch() function's API to support patching at any level of the tree.

/** @jsx h */
import { h, mount, patch } from 'picodom'

const App = props => <h1>{props.title}</h1

let root = <App title='Hello world!' />

mount(document.body, root)

// after state updates
patch(root, (root = <App title='New title' />))

As you can see, it adds a few lines, but perhaps there is a more compact way πŸ€”

As far as introducing a new method to the API, I think it's a good idea. "Mounting" and "patching" are different concerns, and a single API for both would be confusing IMO.

TODO

If you like this direction, I'm happy to make any updates necessary to get it integrated πŸŽ‰

The tests are failing currently, I could probably use some direction there: parentNode is undefined. Throughout the suite patch would need to be updated to mount and the params slightly rearranged.

Thanks!

estrattonbailey commented 6 years ago

Demo

Installs the library from my repo and mounts a tiny app and stateful component.

mindplay-dk commented 6 years ago

Here's the approach I've been using:

function mount(el, update) {
  let old

  return function() {
    patch(el, old, old = update())
  }
}

The function creates a closure for a target element and an update function, which is any function that returns a VNode. Here's an example with a stateless view:

https://jsfiddle.net/mindplay/tuq42u7t/

Because update is a function, this works equally well for views that require a model argument, for a functional component that requires props and children, or pretty much anything.

jorgebucaran commented 6 years ago

@estrattonbailey Thanks, after all, I went with this! :)

import { h, patch } from "patchdom"

document.body.appendChild(
  patch( h("h1", {}, "Hello") )
)

The patch function now returns an element, if none is given, allowing you to append it to a container if that's what you want. If you pass an existing element instead, patchdom will patch that element (attempting to recycle any existing markup), instead of using it as a container like in the past.

estrattonbailey commented 6 years ago

@jorgebucaran beautiful 😍

I should have renamed this PR, lol. My main goal here was was enable patching a VDOM node at a DOM node target. My tweak to patch made a new mount interface useful. It looks like your new version does exactly this, using similar assumptions to mine.

Can't wait to dive into this, 99% positive this is exactly what I needed. Thanks for your work!