diff --git a/CHANGELOG.md b/CHANGELOG.md
index 322a7d2..39adb97 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,32 @@
+## `4.0.0` The routing patch
+This patch changes the way we handle routes. It introduces query string
+support (!), and changes the router to use a lisp-like syntax. It also inverts
+the argument order of effects and reducers to be more intuitive. We also
+managed to sneak in some performance upgrades :sparkles: - We hope you enjoy
+it!
+
+### changes
+- :exclamation: slim down server side rendering API |
+ [issue](https://github.com/yoshuawuyts/choo/issues/191) |
+ [pull-request](https://github.com/yoshuawuyts/choo/pull/203)
+- :exclamation: update router API to be lisp-like
+- :exclamation: swap `state` and `data` argument order |
+ [issue](https://github.com/yoshuawuyts/choo/issues/179)
+- :exclamation: remove `choo/http`. Use [xhr](https://github.com/naugtur/xhr)
+ instead | [pull-request](https://github.com/yoshuawuyts/choo/pull/269)
+- update `router` to use memoization |
+ [issue](https://github.com/yoshuawuyts/sheet-router/issues/17) |
+ [pull-request](https://github.com/yoshuawuyts/sheet-router/pull/34)
+- support inline anchor links |
+ [issue](https://github.com/yoshuawuyts/choo/issues/65)
+- allow bypassing of link clicks in `sheet-router` |
+ [issue](https://github.com/yoshuawuyts/sheet-router/issues/15) |
+ [pull-request](https://github.com/yoshuawuyts/sheet-router/pull/27)
+- update router API to handle hashes by default
+- update router to provide out of the box support for Electron
+- update `location` state to expose `search` parameters (query strings) |
+ [issue](https://github.com/yoshuawuyts/sheet-router/issues/31)
+
## `3.3.0`
Yay, `plugins` now support `wrappers` which is a segway onto HMR, time travel
and other cool plugins. These changes have come through in barracks `v8.3.0`
diff --git a/README.md b/README.md
index 7054fed..dd25958 100644
--- a/README.md
+++ b/README.md
@@ -125,49 +125,50 @@ production, we'd love to hear from you!_
Let's create an input box that changes the content of a textbox in real time.
[Click here to see the app running](http://requirebin.com/?gist=229bceda0334cf30e3044d5f5c600960).
```js
-const choo = require('choo')
-const html = require('choo/html')
-const app = choo()
+var html = require('choo/html')
+var choo = require('choo')
+var app = choo()
app.model({
state: { title: 'Not quite set yet' },
reducers: {
- update: (data, state) => ({ title: data })
+ update: function (state, data) {
+ return { title: data }
+ }
}
})
-const mainView = (state, prev, send) => html`
-
-
+
+
+ `
-app.router((route) => [
- route('/', mainView)
-])
+ function update (e) {
+ send('update', e.target.value)
+ }
+}
-const tree = app.start()
+app.router(['/', mainView])
+
+var tree = app.start()
document.body.appendChild(tree)
```
-To run it, save it as `client.js` and run with [budo] and [es2020]. These tools
-are convenient but any [browserify] based tool should do:
+To run it, save it as `client.js` and run with [bankai][bankai]. `bankai` is
+convenient but any [browserify][browserify] based tool should do:
```sh
-$ budo client.js -p 8080 --open -- -t es2020
-```
+# run and reload on port 8080
+$ bankai client.js -p 8080 --open
-And to save the output to files so it can be deployed, open a new terminal and
-do:
-```bash
-$ mkdir -p 'dist/'
-$ curl 'localhost:8080' > 'dist/index.html'
-$ curl 'localhost:8080/client.js' > 'dist/client.js'
+# compile to static files in `./dist/`
+$ bankai build index.js dist/
+
+# deploy to github pages using `tschaub/gh-pages`
+$ gh-pages -d dist/
```
-All using a couple of shell commands and `.js` files, no grandiose boilerplate
-needed.
## Philosophy
We believe programming should be fun and light, not stern and stressful. It's
@@ -194,47 +195,36 @@ better results and super smiley faces.
## Concepts
`choo` cleanly structures internal data flow, so that all pieces of logic can
-be combined into a nice, cohesive machine. Internally all logic lives within
-`models` that contain several properties. `subscriptions` are functions that
-are called at startup and have `send()` passed in, so they act as read-only
-sources of data. `effects` react to changes, perform an `action` and can then
-post the results. `reducers` take data, modify it, and update the internal
-`state`.
+be combined into a nice, cohesive machine. Roughly speaking there are two parts
+to `choo`: the views and the models. Models take care of state and logic, and
+views are responsible for displaying the interface and responding to user
+interactions.
-Communication of data is done using something called `actions`. Each `action`
-consists of a unique `actionName` and an optional payload of `data`, which can
-be any value.
+All of `choo`'s state is contained in a single object and whenever it changes
+the views receive a new version of the state which they can use to safely
+render a complete new representation of the DOM. The DOM is efficiently updated
+using DOM diffing/patching.
-When a `reducer` modifies `state`, the `router` is called, which in turn calls
-`views`. `views` take `state` and return [DOM] nodes which are then
-efficiently rendered on the screen.
+The logic in choo exist in three different kinds of actions, each with their
+own role: `effects`, `subscriptions` and `reducers`.
+
+- __Effects__ makes an asynchronous operation and calls another action when
+ it's done.
+
+- __Subscriptions__ (called once when the DOM loads) listens for external input
+ like keyboard or WebSocket events and then calls another action.
+
+- __Reducers__ receives the current state and returns an updated version of the
+ state which is then sent to the views.
-In turn when the `views` are rendered, the `user` can interact with elements by
-clicking on them, triggering `actions` which then flow back into the
-application logic. This is the _unidirectional_ architecture of `choo`.
```txt
┌─────────────────┐
│ Subscriptions ─┤ User ───┐
└─ Effects ◀─────┤ ▼
- ┌─ Reducers ◀─────┴──Actions── DOM ◀┐
+ ┌─ Reducers ◀─────┴─────────── DOM ◀┐
│ │
└▶ Router ─────State ───▶ Views ────┘
```
-- __user:__ 🙆
-- __DOM:__ the [Document Object Model][DOM] is what is currently displayed in
- your browser
-- __actions:__ a named event with optional properties attached. Used to call
- `effects` and `reducers` that have been registered in `models`
-- __model:__ optionally namespaced object containing `subscriptions`,
- `effects`, `reducers` and initial `state`
-- __subscriptions:__ read-only data sources that emit `actions`
-- __effects:__ asynchronous functions that emit an `action` when done
-- __reducers:__ synchronous functions that modify `state`
-- __state:__ a single object that contains __all__ the values used in your
- application
-- __router:__ determines which `view` to render
-- __views:__ take `state` and returns a new `DOM tree` that is rendered in the
- browser
### Models
`models` are objects that contain initial `state`, `subscriptions`, `effects`
@@ -249,12 +239,14 @@ Outside the model they're called by `send('todos:add')` and
`state.todos.items`. Inside the namespaced model they're called by
`send('todos:add')` and `state.items`. An example namespaced model:
```js
-const app = choo()
+var app = choo()
app.model({
namespace: 'todos',
state: { items: [] },
reducers: {
- add: (data, state) => ({ items: state.items.concat(data.payload) })
+ add: function (state, data) {
+ return { items: state.items.concat(data.payload) }
+ }
}
})
```
@@ -272,52 +264,52 @@ bulk of your logic will be safely shielded, with only a few points touching ever
part of your application.
### Effects
-Side effects are done through `effects` declared in `app.model()`. Unlike
-`reducers` they cannot modify the state by returning objects, but get a
-callback passed which is used to emit `actions` to handle results. Use effects
-every time you don't need to modify the state object directly, but wish to
-respond to an action.
+`effects` are similar to `reducers` except instead of modifying the state they
+cause side `effects` by interacting servers, databases, DOM APIs, etc. Often
+they'll call a reducer when they're done to update the state. For instance, you
+may have an effect called getUsers that fetches a list of users from a server
+API using AJAX. Assuming the AJAX request completes successfully, the effect
+can pass off the list of users to a reducer called receiveUsers which simply
+updates the state with that list, separating the concerns of interacting with
+an API from updating the application's state.
-A typical `effect` flow looks like:
-
-1. An action is received
-2. An effect is triggered
-3. The effect performs an async call
-4. When the async call is done, either a success or error action is emitted
-5. A reducer catches the action and updates the state
-
-Examples of effects include: performing [xhr] requests (server requests),
-calling multiple `reducers`, persisting state to [localstorage].
+This is an example `effect` that is called once when the application loads and
+calls the `'todos:add'` `reducer` when it receives data from the server:
```js
-const http = require('choo/http')
-const choo = require('choo')
-const app = choo()
+var choo = require('choo')
+var http = require('xhr')
+var app = choo()
+
app.model({
namespace: 'todos',
- state: { items: [] },
+ state: { values: [] },
+ reducers: {
+ add: function (data, state) {
+ return { todos: data }
+ }
+ },
effects: {
- fetch: (data, state, send, done) => {
- http('/todos', (err, res, body) => {
- send('todos:receive', body, done)
+ addAndSave: function (state, data, send, done) {
+ var opts = { body: data.payload, json: true }
+ http.post('/todo', opts, function (err, res, body) {
+ if (err) return done(err)
+ data.payload.id = body.id
+ send('todos:add', data, function (err, value) {
+ if (err) return done(err)
+ done(null, value)
+ })
})
}
},
- reducers: {
- receive: (data, state) => {
- return { items: data }
+ subscriptions: {
+ 'called-once-when-the-app-loads': function (send, done) {
+ send('todos:addAndSave', done)
}
}
})
```
-When an `effect` is done executing, it should call the `done(err, res)`
-callback. This callback is used to communicate when an `effect` is done, handle
-possible errors, and send values back to the caller. You'll probably notice when
-applications become more complex, that composing multiple namespaced models
-using higher level effects becomes really powerful - without becoming
-complicated.
-
### Subscriptions
Subscriptions are a way of receiving data from a source. For example when
listening for events from a server using `SSE` or `Websockets` for a
@@ -325,23 +317,29 @@ chat app, or when catching keyboard input for a videogame.
An example subscription that logs `"dog?"` every second:
```js
-const app = choo()
+var choo = require('choo')
+
+var app = choo()
app.model({
namespace: 'app',
- subscriptions: [
- (send, done) => {
- setInterval(() => {
- send('app:print', { payload: 'dog?', myOtherValue: 1000 }, (err) => {
+ effects: {
+ print: function (state, data) {
+ console.log(data.payload)
+ }
+ },
+ subscriptions: {
+ callDog: function (send, done) {
+ setInterval(function () {
+ var data = { payload: 'dog?', myOtherValue: 1000 }
+ send('app:print', data, function (err) {
if (err) return done(err)
})
}, 1000)
}
- ],
- effects: {
- print: (data, state) => console.log(data.payload)
}
})
```
+
If a `subscription` runs into an error, it can call `done(err)` to signal the
error to the error hook.
@@ -350,13 +348,13 @@ The `router` manages which `views` are rendered at any given time. It also
supports rendering a default `view` if no routes match.
```js
-const app = choo()
-app.router('/404', (route) => [
- route('/', require('./views/empty')),
- route('/404', require('./views/error')),
- route('/:mailbox', require('./views/mailbox'), [
- route('/:message', require('./views/email'))
- ])
+var app = choo()
+app.router({ default: '/404' }, [
+ [ '/', require('./views/empty') ],
+ [ '/404', require('./views/error') ],
+ [ '/:mailbox', require('./views/mailbox'), [
+ [ '/:message', require('./views/email') ]
+ ]]
])
```
@@ -372,21 +370,29 @@ from within namespaced `models`, and usage should preferably be kept to a
minimum. Changing views all over the place tends to lead to messiness.
### Views
-Views are pure functions that return a DOM tree for the router to render. They’re passed the current state, and any time the state changes they’re run again with the new state.
+Views are pure functions that return a DOM tree for the router to render.
+They’re passed the current state, and any time the state changes they’re run
+again with the new state.
-Views are also passed the `send` function, which they can use to dispatch actions that can update the state. For example, the DOM tree can have an `onclick` handler that dispatches an `add` action.
+Views are also passed the `send` function, which they can use to dispatch
+actions that can update the state. For example, the DOM tree can have an
+`onclick` handler that dispatches an `add` action.
-```javascript
-const view = (state, prev, send) => {
+```js
+function view (state, prev, send) {
return html`
Total todos: ${state.todos.length}
-
-
`
+
+
+ `
+
+ function addTodo (e) {
+ send('add', { title: 'demo' })
+ }
}
```
+
In this example, when the `Add` button is clicked, the view will dispatch an
`add` action that the model’s `add` reducer will receive. [As seen
above](#models), the reducer will add an item to the state’s `todos` array. The
@@ -401,13 +407,13 @@ somewhere. This is done through something called `plugins`. Plugins are objects
that contain `hook` and `wrap` functions and are passed to `app.use()`:
```js
-const log = require('choo-log')
-const choo = require('choo')
-const app = choo()
+var log = require('choo-log')
+var choo = require('choo')
+var app = choo()
app.use(log())
-const tree = app.start()
+var tree = app.start()
document.body.appendChild(tree)
```
@@ -427,9 +433,9 @@ and `wrappers` are available, head on over to [app.use()](#appusehooks).
Using `choo` in a project? Show off which version you've used using a badge:
-[](https://github.com/yoshuawuyts/choo)
+[](https://github.com/yoshuawuyts/choo)
```md
-[](https://github.com/yoshuawuyts/choo)
+[](https://github.com/yoshuawuyts/choo)
```
## API
@@ -449,9 +455,9 @@ arguments:
and handlers in other models
- __state:__ initial values of `state` inside the model
- __reducers:__ synchronous operations that modify state. Triggered by
- `actions`. Signature of `(data, state)`.
+ `actions`. Signature of `(state, data)`.
- __effects:__ asynchronous operations that don't modify state directly.
- Triggered by `actions`, can call `actions`. Signature of `(data, state,
+ Triggered by `actions`, can call `actions`. Signature of `(state, data,
send, done)`
- __subscriptions:__ asynchronous read-only operations that don't modify state
directly. Can call `actions`. Signature of `(send, done)`.
@@ -490,9 +496,9 @@ There are several `hooks` and `wrappers` that are picked up by `choo`:
- __onError(err, state, createSend):__ called when an `effect` or
`subscription` emit an error. If no handler is passed, the default handler
will `throw` on each error.
-- __onAction(data, state, name, caller, createSend):__ called when an
+- __onAction(state, data, name, caller, createSend):__ called when an
`action` is fired.
-- __onStateChange(data, state, prev, caller, createSend):__ called after a
+- __onStateChange(state, data, prev, caller, createSend):__ called after a
reducer changes the `state`.
- __wrapSubscriptions(fn):__ wraps a `subscription` to add custom behavior
- __wrapReducers(fn):__ wraps a `reducer` to add custom behavior
@@ -523,12 +529,9 @@ optional state object. When calling `.toString()` instead of `.start()`, all
calls to `send()` are disabled, and `subscriptions`, `effects` and `reducers`
aren't loaded.
-### tree = app.start(rootId?, opts)
+### tree = app.start(opts)
Start the application. Returns a tree of DOM nodes that can be mounted using
-`document.body.appendChild()`. If a valid `id` selector is passed in as the
-first argument, the tree will diff against the selected node rather than be
-returned. This is useful for [rehydration](https://github.com/yoshuawuyts/choo-handbook/blob/master/rendering-in-node.md#rehydration). Opts can contain the
-following values:
+`document.body.appendChild()`. Opts can contain the following values:
- __opts.history:__ default: `true`. Enable a `subscription` to the browser
history API. e.g. updates the internal `location.href` state whenever the
browsers "forward" and "backward" buttons are pressed.
@@ -549,10 +552,14 @@ current `state`, `prev` is the last state, `state.params` is URI partials and
To create listeners for events, create interpolated attributes on elements.
```js
-const html = require('choo/html')
+var html = require('choo/html')
html`
-
+
`
+
+function log (e) {
+ console.log(e)
+}
```
Example listeners include: `onclick`, `onsubmit`, `oninput`, `onkeydown`,
`onkeyup`. A full list can be found [at the yo-yo
@@ -660,8 +667,8 @@ Consider running some of the following:
- [unassertify](https://github.com/twada/unassertify) - remove `assert()`
statements which reduces file size. Use as a `--global` transform
- [es2020](https://github.com/yoshuawuyts/es2020) - backport `const`,
- `fat-arrows` and `template strings` to older browsers. Should be run as a
- `--global` transform
+ `arrow functions` and `template strings` to older browsers. Should be run as
+ a `--global` transform
- [yo-yoify](https://github.com/shama/yo-yoify) - replace the internal `hyperx`
dependency with `document.createElement` calls; greatly speeds up performance
too
@@ -676,8 +683,8 @@ Consider running some of the following:
### Choo + Internet Explorer & Safari
Out of the box `choo` only supports runtimes which support:
* `const`
-* `fat-arrow` functions (e.g. `() => {}`)
-* `template-strings`
+* `arrow functions` (e.g. `() => {}`)
+* `template strings`
This does not include Safari 9 or any version of IE. If support for these
platforms is required you will have to provide some sort of transform that
@@ -814,35 +821,18 @@ Become a backer, and buy us a coffee (or perhaps lunch?) every month or so.
-
## License
[MIT](https://tldrlegal.com/license/mit-license)
+[bankai]: https://github.com/yoshuawuyts/bankai
[bel]: https://github.com/shama/bel
-[big-o]: https://rob-bell.net/2009/06/a-beginners-guide-to-big-o-notation/
-[bl]: https://github.com/rvagg/bl
[browserify]: https://github.com/substack/node-browserify
[budo]: https://github.com/mattdesl/budo
-[DOM]: https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model
-[dom]: https://en.wikipedia.org/wiki/Document_Object_Model
[es2020]: https://github.com/yoshuawuyts/es2020
[handbook]: https://github.com/yoshuawuyts/choo-handbook
-[html-input]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input
[hyperx]: https://github.com/substack/hyperx
[inu]: https://github.com/ahdinosaur/inu
-[isomorphic]: https://en.wikipedia.org/wiki/Isomorphism
-[keyboard-support]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Browser_compatibility
-[localstorage]: https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage
-[module-parent]: https://nodejs.org/dist/latest-v6.x/docs/api/modules.html#modules_module_parent
[morphdom-bench]: https://github.com/patrick-steele-idem/morphdom#benchmarks
[morphdom]: https://github.com/patrick-steele-idem/morphdom
-[nginx]: http://nginx.org/
-[qps]: https://en.wikipedia.org/wiki/Queries_per_second
[sheet-router]: https://github.com/yoshuawuyts/sheet-router
-[sse-reconnect]: http://stackoverflow.com/questions/24564030/is-an-eventsource-sse-supposed-to-try-to-reconnect-indefinitely
-[sse]: https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events
-[varnish]: https://varnish-cache.org
-[ws-reconnect]: http://stackoverflow.com/questions/13797262/how-to-reconnect-to-websocket-after-close-connection
-[ws]: https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API
-[xhr]: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
[yo-yo]: https://github.com/maxogden/yo-yo
diff --git a/examples/async-counter/client.js b/examples/async-counter/client.js
index b64180a..71cce36 100644
--- a/examples/async-counter/client.js
+++ b/examples/async-counter/client.js
@@ -8,20 +8,20 @@ app.model({
counter: 0
},
reducers: {
- increment: (data, state) => ({ counter: state.counter + 1 }),
- decrement: (data, state) => ({ counter: state.counter - 1 })
+ increment: (state, data) => ({ counter: state.counter + 1 }),
+ decrement: (state, data) => ({ counter: state.counter - 1 })
},
effects: {
- incrementAsync: function (data, state, send, done) {
+ incrementAsync: function (state, data, send, done) {
setTimeout(() => send('increment', done), 1000)
},
- decrementAsync: function (data, state, send, done) {
+ decrementAsync: function (state, data, send, done) {
setTimeout(() => send('decrement', done), 1000)
}
}
})
-const mainView = (state, prev, send) => {
+function mainView (state, prev, send) {
const count = state.counter
return html`
@@ -36,9 +36,7 @@ const mainView = (state, prev, send) => {
`
}
-app.router((route) => [
- route('/', mainView)
-])
+app.router([ '/', mainView ])
const tree = app.start()
document.body.appendChild(tree)
diff --git a/examples/async-counter/package.json b/examples/async-counter/package.json
index a923e54..45f3783 100644
--- a/examples/async-counter/package.json
+++ b/examples/async-counter/package.json
@@ -4,13 +4,13 @@
"description": "",
"main": "client.js",
"scripts": {
- "start": "budo client.js -p 8080"
+ "start": "bankai start --entry=client -p 8080"
},
"keywords": [],
"author": "Juan Soto ",
"license": "ISC",
"dependencies": {
- "budo": "^8.3.0",
+ "bankai": "^3.2.0",
"plur": "^2.1.2"
}
}
diff --git a/examples/http/client.js b/examples/http/client.js
index 7ca0145..b2c92ed 100644
--- a/examples/http/client.js
+++ b/examples/http/client.js
@@ -4,18 +4,19 @@ const mainView = require('./views/main')
const app = choo({
onError: function (err, state, createSend) {
+ console.trace()
console.groupCollapsed(`Error: ${err.message}`)
console.error(err)
console.groupEnd()
const send = createSend('onError: ')
send('app:error', err)
},
- onAction: function (data, state, name, caller, createSend) {
+ onAction: function (state, data, name, caller, createSend) {
console.groupCollapsed(`Action: ${caller} -> ${name}`)
console.log(data)
console.groupEnd()
},
- onStateChange: function (data, state, prev, createSend) {
+ onStateChange: function (state, data, prev, createSend) {
console.groupCollapsed('State')
console.log(prev)
console.log(state)
@@ -26,9 +27,7 @@ const app = choo({
app.model(require('./models/error'))
app.model(require('./models/api'))
-app.router((route) => [
- route('/', mainView)
-])
+app.router(['/', mainView])
const tree = app.start()
document.body.appendChild(tree)
diff --git a/examples/http/models/api.js b/examples/http/models/api.js
index 9fd5826..5d9067a 100644
--- a/examples/http/models/api.js
+++ b/examples/http/models/api.js
@@ -6,13 +6,13 @@ module.exports = {
title: 'Button pushing machine 3000'
},
reducers: {
- set: (data, state) => ({ 'title': data })
+ set: (state, data) => ({ 'title': data })
},
effects: {
- good: function (data, state, send, done) {
+ good: function (state, data, send, done) {
request('/good', send, done)
},
- bad: (data, state, send, done) => request('/bad', send, done)
+ bad: (state, data, send, done) => request('/bad', send, done)
}
}
diff --git a/examples/http/models/error.js b/examples/http/models/error.js
index bd1620a..4530791 100644
--- a/examples/http/models/error.js
+++ b/examples/http/models/error.js
@@ -15,13 +15,13 @@ module.exports = {
triggerTime: null
},
reducers: {
- setError: function (data, state) {
+ setError: function (state, data) {
return {
errors: state.errors.concat(data.message),
errorTimeDone: data.errorTimeDone
}
},
- 'delError': function (data, state) {
+ 'delError': function (state, data) {
state.errors.shift()
return { errors: state.errors }
}
diff --git a/examples/mailbox/client.js b/examples/mailbox/client.js
index a5f118f..aceae2c 100644
--- a/examples/mailbox/client.js
+++ b/examples/mailbox/client.js
@@ -1,19 +1,22 @@
-const choo = require('../../')
+const log = require('choo-log')
const sf = require('sheetify')
+const choo = require('../../')
+
sf('css-wipe/dest/bundle')
const app = choo()
+app.use(log())
app.model(require('./models/inbox'))
app.model(require('./models/spam'))
app.model(require('./models/sent'))
-app.router((route) => [
- route('/', require('./views/empty')),
- route('/:mailbox', require('./views/mailbox'), [
- route('/:message', require('./views/email'))
- ])
+app.router([
+ ['/', require('./views/empty')],
+ ['/:mailbox', require('./views/mailbox'), [
+ ['/:message', require('./views/email')]
+ ]]
])
const tree = app.start()
diff --git a/examples/mailbox/package.json b/examples/mailbox/package.json
index c14dfc1..290e124 100644
--- a/examples/mailbox/package.json
+++ b/examples/mailbox/package.json
@@ -9,6 +9,7 @@
"author": "Yoshua Wuyts ",
"license": "ISC",
"dependencies": {
+ "choo-log": "^1.4.1",
"css-wipe": "^4.2.1",
"dateformat": "^1.0.12",
"pathname-match": "^1.1.3",
diff --git a/examples/mailbox/views/mailbox.js b/examples/mailbox/views/mailbox.js
index 1fb173e..582a654 100644
--- a/examples/mailbox/views/mailbox.js
+++ b/examples/mailbox/views/mailbox.js
@@ -7,6 +7,7 @@ const nav = require('../elements/nav')
module.exports = function (state, prev, send) {
return html`
+
${pathname(state, prev, send)}
${nav(state, prev, send)}
@@ -14,4 +15,8 @@ module.exports = function (state, prev, send) {
`
+
+ function goHome () {
+ send('location:set', { pathname: '/' })
+ }
}
diff --git a/examples/server-rendering/client.js b/examples/server-rendering/client.js
index 7e8283c..3bcd8f6 100644
--- a/examples/server-rendering/client.js
+++ b/examples/server-rendering/client.js
@@ -1,6 +1,7 @@
+const mount = require('../../mount')
const choo = require('../../')
-const mainView = require('./views/main')
+const mainView = require('./view')
const app = choo()
@@ -12,12 +13,11 @@ app.model({
}
})
-app.router((route) => [
- route('/', mainView)
-])
+app.router(['/', mainView])
if (module.parent) {
module.exports = app
} else {
- app.start('#app-root')
+ const tree = app.start()
+ mount('#app-root', tree)
}
diff --git a/examples/server-rendering/views/main.js b/examples/server-rendering/view.js
similarity index 96%
rename from examples/server-rendering/views/main.js
rename to examples/server-rendering/view.js
index f59e9ab..5e2510c 100644
--- a/examples/server-rendering/views/main.js
+++ b/examples/server-rendering/view.js
@@ -1,5 +1,5 @@
const assert = require('assert')
-const html = require('../../../html')
+const html = require('../../html')
module.exports = function (state, prev, send) {
const serverMessage = state.message.server
diff --git a/examples/sse/client.js b/examples/sse/client.js
index 8ed40cc..0552fe4 100644
--- a/examples/sse/client.js
+++ b/examples/sse/client.js
@@ -3,14 +3,12 @@ const html = require('../../html')
const app = choo()
app.model(createModel())
-app.router((route) => [
- route('/', mainView)
-])
+app.router(['/', mainView])
const tree = app.start()
document.body.appendChild(tree)
-function mainView (params, state, send) {
+function mainView (state, prev, send) {
return html`