virtual-app

A wrapper around [virtual-dom](https://npmjs.com/virtual-dom), [virtual-raf](https://npmjs.com/virtual-raf), & [store-emitter](https://npmjs.com/store-emitter) that provides redux-like, unidirectional state management paired with virtual-dom.

Usage no npm install needed!

<script type="module">
  import virtualApp from 'https://cdn.skypack.dev/virtual-app';
</script>

README

virtual-app

virtual-app logo

A wrapper around virtual-dom, virtual-raf, & store-emitter that provides redux-like, unidirectional state management paired with virtual-dom.

What is this

I keep writing essentially this module with each new project I build that uses virtual-dom.

You could definitely use virtual-dom, virtual-raf, and store-emitter separately (and switch them out for other modules) if this doesn't fit your needs exactly.

Breaking Changes

  • 3.0.0 : virtual-app no longer appends your app to the dom for you, it returns a dom tree that you can append or turn into an html string

Install

npm install --save virtual-app

Example

var extend = require('xtend')
var vdom = require('virtual-dom')
var createApp = require('virtual-app')
var h = vdom.h

/*
* create the app passing in virtual-dom
*/
var app = createApp(vdom)

/*
* The only way to modify state is to trigger an action
* the modifer function is where you change state based on the type of an action
*/
function modifier (action, state) {
  if (action.type === 'example') {
    return extend(state, { example: true })
  } else if (action.type === 'title') {
    return extend(state, { title: action.title })
  }
}

/*
* Start the application with the modifier function and the initial state as args
* `app.start()` returns the `render()` function that's used to render your virtual tree
*/
var render = app.start(modifier, {
  example: false
})

/*
* return the tree of your app for rendering
* this returns a real dom tree that can be appended to your web page
*/
var domTree = render(function (state) {
  return h('.app', [
    h('h1', state.title),
    h('label', 'Write a new title: '),
    h('input', {
      type: 'text',
      placeholder: state.title,
      oninput: function (e) {
        app.store({ type: 'title', title: e.target.value })
      }
    })
  ])
})

/*
* get the new state every time an action updates the state
*/
app.on('*', function (action, state, oldState) {
  console.log('action happened so here is the new state:', state)
})

/*
* listen to only specific action types
*/
app.on('title', function (action, state, oldState) {
  console.log('state has a new title:', state.title)
})

/*
* trigger an action using `app.store()`
*/
app.store({
  type: 'example'
})

/*
* action objects must have a `type` property, and can have any other arbitrary properties
*/
app.store({
  type: 'title',
  title: 'awesome example'
})

/*
* append the dom tree to the page
*/

document.body.appendChild(domTree)

see also, example-server.js for a server-side rendering example

API

app.h

virtual-dom h function.

Parameters

  • selector
  • options
  • children

app.on

Event listener

Parameters

  • event String – can be an asterisk * to listen to all actions or the type of a specific action
  • callback Function – callback that provides action, state, and oldState arguments

Examples

app.on('*', function (action, state, oldState) {
  // do something with the new `state`
})

app.send

Bind an event to a component. Convenience wrapper around app.store.

Parameters

  • action Object
    • action.type String – an identifier for the type of the action
  • flag String – call preventDefault on event (default: true)

Examples

app.h('button', { onclick: app.send({ type: 'increment' })}, 'click me')

app.start

Start the app.

Parameters

  • modifier Function – function that determines how the state will change based on the action
  • initialState Object – the state of the application when it loads

Examples

function modifier (action, state) {
  if (action.type === 'example') {
    return { example: true }
  }
}

var render = app.start(modifier, {
  example: false
})

render(function (state) {
  if (state.example) {
    return app.h('h1', 'this is an example')
  } else {
    return app.h('h1', 'what i thought this was an example')
  }
})

app.store

Trigger an event that gets passed through the modifier function to change the state. A type property is required. You can add any other arbitrary properties.

Parameters

  • action Object
    • action.type String – an identifier for the type of the action

Examples

app.store({
  type: 'example'
  example: true
})

createVirtualApp

Create the app.

Parameters

  • vdom Object – the full virtual-dom module returned by require('virtual-dom')

Examples

var createVirtualApp = require('virtual-app')

var app = createVirtualApp(require('virtual-dom'))

render

Render the application. This function is returned by the app.start() method.

Parameters

  • callback Function – define the virtual tree of your application and return it from this callback

Returns

  • Object - a dom tree

Examples

var render = app.start(modifier, { food: 'pizza' })

var domTree = render(function (state) {
  return app.h('h1', state.food)
})

License

MIT