{"id":13839222,"url":"https://github.com/sethvincent/virtual-app","last_synced_at":"2025-07-20T06:33:14.483Z","repository":{"id":57392768,"uuid":"47801624","full_name":"sethvincent/virtual-app","owner":"sethvincent","description":"Provides redux-like, unidirectional state management paired with virtual-dom.","archived":false,"fork":false,"pushed_at":"2016-02-10T17:53:44.000Z","size":24,"stargazers_count":75,"open_issues_count":6,"forks_count":5,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-06-24T05:04:29.434Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sethvincent.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-12-11T03:03:37.000Z","updated_at":"2024-09-29T10:56:00.000Z","dependencies_parsed_at":"2022-08-27T01:53:01.187Z","dependency_job_id":null,"html_url":"https://github.com/sethvincent/virtual-app","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/sethvincent/virtual-app","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sethvincent%2Fvirtual-app","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sethvincent%2Fvirtual-app/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sethvincent%2Fvirtual-app/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sethvincent%2Fvirtual-app/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sethvincent","download_url":"https://codeload.github.com/sethvincent/virtual-app/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sethvincent%2Fvirtual-app/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266076350,"owners_count":23872741,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-04T16:00:55.138Z","updated_at":"2025-07-20T06:33:14.448Z","avatar_url":"https://github.com/sethvincent.png","language":"JavaScript","funding_links":[],"categories":["Modules"],"sub_categories":["Frameworks / libraries that depend on virtual-dom"],"readme":"# virtual-app\n\u003cimg\n  alt=\"virtual-app logo\"\n  height=\"100\"\n  style=\"max-width: 100%\"\n  data-canonical-src=\"https://github.com/yoshuawuyts/virtual-app-logo\"\n  src=\"https://raw.githubusercontent.com/yoshuawuyts/virtual-app-logo/master/512.png\"\u003e\n\nA wrapper around [virtual-dom](https://npmjs.com/virtual-dom), [virtual-raf](https://npmjs.com/virtual-raf), \u0026 [store-emitter](https://npmjs.com/store-emitter) that provides redux-like, unidirectional state management paired with virtual-dom.\n\n## What is this\n\nI keep writing essentially this module with each new project I build that uses virtual-dom.\n\nYou 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.\n\n## Breaking Changes\n- 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\n\n## Install\n\n    npm install --save virtual-app\n\n## Example\n\n```js\nvar extend = require('xtend')\nvar vdom = require('virtual-dom')\nvar createApp = require('virtual-app')\nvar h = vdom.h\n\n/*\n* create the app passing in virtual-dom\n*/\nvar app = createApp(vdom)\n\n/*\n* The only way to modify state is to trigger an action\n* the modifer function is where you change state based on the type of an action\n*/\nfunction modifier (action, state) {\n  if (action.type === 'example') {\n    return extend(state, { example: true })\n  } else if (action.type === 'title') {\n    return extend(state, { title: action.title })\n  }\n}\n\n/*\n* Start the application with the modifier function and the initial state as args\n* `app.start()` returns the `render()` function that's used to render your virtual tree\n*/\nvar render = app.start(modifier, {\n  example: false\n})\n\n/*\n* return the tree of your app for rendering\n* this returns a real dom tree that can be appended to your web page\n*/\nvar domTree = render(function (state) {\n  return h('.app', [\n    h('h1', state.title),\n    h('label', 'Write a new title: '),\n    h('input', {\n      type: 'text',\n      placeholder: state.title,\n      oninput: function (e) {\n        app.store({ type: 'title', title: e.target.value })\n      }\n    })\n  ])\n})\n\n/*\n* get the new state every time an action updates the state\n*/\napp.on('*', function (action, state, oldState) {\n  console.log('action happened so here is the new state:', state)\n})\n\n/*\n* listen to only specific action types\n*/\napp.on('title', function (action, state, oldState) {\n  console.log('state has a new title:', state.title)\n})\n\n/*\n* trigger an action using `app.store()`\n*/\napp.store({\n  type: 'example'\n})\n\n/*\n* action objects must have a `type` property, and can have any other arbitrary properties\n*/\napp.store({\n  type: 'title',\n  title: 'awesome example'\n})\n\n/*\n* append the dom tree to the page\n*/\n\ndocument.body.appendChild(domTree)\n```\n\nsee also, example-server.js for a server-side rendering example\n\n## API\n\n### app.h\n\nvirtual-dom `h` function.\n\n**Parameters**\n\n-   `selector`  \n-   `options`  \n-   `children`  \n\n### app.on\n\nEvent listener\n\n**Parameters**\n\n-   `event` **String** – can be an asterisk `*` to listen to all actions or the type of a specific action\n-   `callback` **Function** – callback that provides `action`, `state`, and `oldState` arguments\n\n**Examples**\n\n```javascript\napp.on('*', function (action, state, oldState) {\n  // do something with the new `state`\n})\n```\n\n### app.send\n\nBind an event to a component. Convenience wrapper around `app.store`.\n\n**Parameters**\n\n-   `action` **Object** \n    -   `action.type` **String** – an identifier for the type of the action\n-   `flag` **String** – call preventDefault on event (default: true)\n\n**Examples**\n\n```javascript\napp.h('button', { onclick: app.send({ type: 'increment' })}, 'click me')\n```\n\n### app.start\n\nStart the app.\n\n**Parameters**\n\n-   `modifier` **Function** – function that determines how the state will change based on the action\n-   `initialState` **Object** – the state of the application when it loads\n\n**Examples**\n\n```javascript\nfunction modifier (action, state) {\n  if (action.type === 'example') {\n    return { example: true }\n  }\n}\n\nvar render = app.start(modifier, {\n  example: false\n})\n\nrender(function (state) {\n  if (state.example) {\n    return app.h('h1', 'this is an example')\n  } else {\n    return app.h('h1', 'what i thought this was an example')\n  }\n})\n```\n\n### app.store\n\nTrigger 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.\n\n**Parameters**\n\n-   `action` **Object** \n    -   `action.type` **String** – an identifier for the type of the action\n\n**Examples**\n\n```javascript\napp.store({\n  type: 'example'\n  example: true\n})\n```\n\n### createVirtualApp\n\nCreate the app.\n\n**Parameters**\n\n-   `vdom` **Object** – the full virtual-dom module returned by `require('virtual-dom')`\n\n**Examples**\n\n```javascript\nvar createVirtualApp = require('virtual-app')\n\nvar app = createVirtualApp(require('virtual-dom'))\n```\n\n### render\n\nRender the application. This function is returned by the `app.start()` method.\n\n**Parameters**\n\n-   `callback` **Function** – define the virtual tree of your application and return it from this callback\n\n**Returns**\n- **Object** - a dom tree\n\n**Examples**\n\n```javascript\nvar render = app.start(modifier, { food: 'pizza' })\n\nvar domTree = render(function (state) {\n  return app.h('h1', state.food)\n})\n```\n\n## License\n\n[MIT](LICENSE.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsethvincent%2Fvirtual-app","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsethvincent%2Fvirtual-app","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsethvincent%2Fvirtual-app/lists"}