diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c343570..4b0895a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,11 +12,14 @@ we support - while secretly sneaking in some performance upgrades. Enjoy! - [choo-handbook/upgrading/4.0.0]() ### changes -- slim down server side rendering API | +- :exclamation: slim down server side rendering API | [issue](https://github.com/yoshuawuyts/choo/issues/191) | [pull-request](https://github.com/yoshuawuyts/choo/pull/203) -- update router API to be lisp-like | [issue]() | [pull-request]() -- update `router` to use thunking | +- :exclamation: update router API to be lisp-like | [issue]() | + [pull-request]() +- :exclamation: swap `state` and `data` argument order | + [issue](https://github.com/yoshuawuyts/choo/issues/179) +- 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 | @@ -27,8 +30,6 @@ we support - while secretly sneaking in some performance upgrades. Enjoy! - update router API to handle hashes by default - update `location` state to expose `search` parameters (query strings) | [issue](https://github.com/yoshuawuyts/sheet-router/issues/31) -- swap `state` and `data` argument order | - [issue](https://github.com/yoshuawuyts/choo/issues/179) ## `3.2.0` Wooh, `plugins` are a first class citizen now thanks to the `.use()` API. It's diff --git a/README.md b/README.md index a1bd018e..2fb0cc02 100644 --- a/README.md +++ b/README.md @@ -129,7 +129,7 @@ const app = choo() app.model({ state: { title: 'Not quite set yet' }, reducers: { - update: (data, state) => ({ title: data }) + update: (state, data) => ({ title: data }) } }) @@ -252,7 +252,7 @@ app.model({ namespace: 'todos', state: { items: [] }, reducers: { - add: (data, state) => ({ items: state.items.concat(data.payload) }) + add: (state, data) => ({ items: state.items.concat(data.payload) }) } }) ``` @@ -297,7 +297,7 @@ app.model({ namespace: 'todos', state: { items: [] }, effects: { - addAndSave: (data, state, send, done) => { + addAndSave: (state, data, send, done) => { http.post('/todo', {body: data.payload, json: true}, (err, res, body) => { data.payload.id = body.id send('todos:add', data, done) @@ -305,7 +305,7 @@ app.model({ } }, reducers: { - add: (data, state) => ({ items: state.items.concat(data.payload) }) + add: (state, data) => ({ items: state.items.concat(data.payload) }) } }) ``` @@ -337,7 +337,7 @@ app.model({ } ], effects: { - print: (data, state) => console.log(data.payload) + print: (state, data) => console.log(data.payload) } }) ``` @@ -448,9 +448,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 +490,9 @@ There are several `hooks` 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(action, state, name, caller, createSend):__ called when an +- __onAction(state, data, name, caller, createSend):__ called when an `action` is fired. -- __onStateChange(action, state, prev, caller, createSend):__ called after a +- __onStateChange(state, data, prev, caller, createSend):__ called after a reducer changes the `state`. __:warning: Warning :warning:: plugins should only be used as a last resort. diff --git a/examples/async-counter/client.js b/examples/async-counter/client.js index 03539d26..71cce36f 100644 --- a/examples/async-counter/client.js +++ b/examples/async-counter/client.js @@ -8,14 +8,14 @@ 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) } } diff --git a/examples/http/client.js b/examples/http/client.js index 69e4569e..b2c92ed5 100644 --- a/examples/http/client.js +++ b/examples/http/client.js @@ -11,12 +11,12 @@ const app = choo({ 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) diff --git a/examples/http/models/api.js b/examples/http/models/api.js index 9fd58263..5d9067a3 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 bd1620a4..4530791b 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/sse/client.js b/examples/sse/client.js index 1888cf46..0552fe40 100644 --- a/examples/sse/client.js +++ b/examples/sse/client.js @@ -33,16 +33,16 @@ function createModel () { } ], reducers: { - 'print': (data, state) => { + 'print': (state, data) => { return ({ msg: state.msg + ' ' + data.payload }) } }, effects: { - close: (data, state, send, done) => { + close: (state, data, send, done) => { stream.close() done() }, - error: (data, state, send, done) => { + error: (state, data, send, done) => { console.error(`error: ${data.payload}`) done() } diff --git a/examples/stopwatch/models/stopwatch.js b/examples/stopwatch/models/stopwatch.js index cb540710..dec45543 100644 --- a/examples/stopwatch/models/stopwatch.js +++ b/examples/stopwatch/models/stopwatch.js @@ -8,14 +8,14 @@ module.exports = { laps: [] }, reducers: { - start: (data, state) => ({ start: true, startTime: Date.now() - state.elapsed }), - stop: (data, state) => ({ start: false }), - update: (data, state) => ({ elapsed: data }), - reset: (data, state) => ({ startTime: Date.now(), elapsed: 0, laps: [] }), - add: (data, state) => ({ laps: state.laps.concat(data) }) + start: (state, data) => ({ start: true, startTime: Date.now() - state.elapsed }), + stop: (state, data) => ({ start: false }), + update: (state, data) => ({ elapsed: data }), + reset: (state, data) => ({ startTime: Date.now(), elapsed: 0, laps: [] }), + add: (state, data) => ({ laps: state.laps.concat(data) }) }, effects: { - now: (data, state, send, done) => { + now: (state, data, send, done) => { if (state.start) { let elapsed = data - state.startTime send('update', elapsed, done) diff --git a/examples/title/client.js b/examples/title/client.js index c04ea759..41bb0ff5 100644 --- a/examples/title/client.js +++ b/examples/title/client.js @@ -8,10 +8,10 @@ app.model({ title: 'my demo app' }, reducers: { - update: (data, state) => ({ title: data.payload }) + update: (state, data) => ({ title: data.payload }) }, effects: { - update: (data, state, send, done) => { + update: (state, data, send, done) => { document.title = data.payload done() } diff --git a/examples/vanilla/index.html b/examples/vanilla/index.html index 63875ed1..72dcd718 100644 --- a/examples/vanilla/index.html +++ b/examples/vanilla/index.html @@ -12,8 +12,8 @@ namespace: 'counter', state: { count: 0 }, reducers: { - increment: (data, state) => ({count: state.count + 1}), - decrement: (data, state) => ({count: state.count - 1}) + increment: (state, data) => ({count: state.count + 1}), + decrement: (state, data) => ({count: state.count - 1}) } }) diff --git a/index.js b/index.js index 4b41db99..ff68287b 100644 --- a/index.js +++ b/index.js @@ -70,7 +70,7 @@ function choo (opts) { // update the DOM after every state mutation // (obj, obj, obj, str, fn) -> null - function render (data, state, prev, name, createSend) { + function render (state, data, prev, name, createSend) { if (!_frame) { _frame = nanoraf(function (state, prev) { const newTree = _router(state.location.pathname, state, prev) diff --git a/package.json b/package.json index add750c7..1ebb34b6 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ ], "license": "MIT", "dependencies": { - "barracks": "^8.1.1", + "barracks": "^9.0.0", "document-ready": "~1.0.2", "global": "^4.3.0", "hash-match": "^1.0.2", @@ -58,7 +58,7 @@ "es2020": "^1.0.1", "geval": "~2.1.1", "gzip-size-cli": "^1.0.0", - "insert-css": "^0.2.0", + "insert-css": "^1.0.0", "istanbul": "^0.4.4", "min-document": "~2.18.0", "pretty-bytes-cli": "^1.0.0", diff --git a/tests/browser/basic.js b/tests/browser/basic.js index b67e6bee..087310d8 100644 --- a/tests/browser/basic.js +++ b/tests/browser/basic.js @@ -17,16 +17,16 @@ test('state is immutable', function (t) { state: state, namespace: 'test', reducers: { - 'no-reducer-mutate': (action, state) => { + 'no-reducer-mutate': (state, data) => { return {} }, - 'mutate-on-return': (action, state) => { - delete action.type - return action + 'mutate-on-return': (state, data) => { + delete data.type + return data } }, effects: { - 'triggers-reducers': (action, state, send, done) => { + 'triggers-reducers': (state, data, send, done) => { send('test:mutate-on-return', {beep: 'barp'}, done) } } diff --git a/tests/browser/hooks.js b/tests/browser/hooks.js index 8e2faab2..80de35bf 100644 --- a/tests/browser/hooks.js +++ b/tests/browser/hooks.js @@ -10,16 +10,16 @@ test('hooks', function (t) { onError: function (err) { t.equal(err.message, 'effect error', 'onError: receives err') }, - onAction: function (action, state, name, caller, createSend) { + onAction: function (state, data, name, caller, createSend) { if (name === 'explodes') return - t.deepEqual(action, {foo: 'bar'}, 'onAction: action data') + t.deepEqual(data, {foo: 'bar'}, 'onAction: action data') t.equal(state.clicks, 0, 'onAction: current state: 0 clicks') - t.equal(name, 'click', 'onAction: action name') + t.equal(name, 'click', 'onAction: data name') t.equal(caller, 'view: /', 'onAction: caller name') t.equal(typeof createSend, 'function', 'onAction: createSend fn') }, - onStateChange: function (action, state, prev, createSend) { - t.deepEqual(action, {foo: 'bar'}, 'onState: action data') + onStateChange: function (state, data, prev, createSend) { + t.deepEqual(data, {foo: 'bar'}, 'onState: action data') t.deepEqual(state.clicks, 1, 'onState: new state: 1 clicks') t.deepEqual(prev.clicks, 0, 'onState: prev state: 0 clicks') } @@ -30,10 +30,10 @@ test('hooks', function (t) { clicks: 0 }, reducers: { - click: (action, state) => ({clicks: state.clicks + 1}) + click: (state, data) => ({clicks: state.clicks + 1}) }, effects: { - explodes: (action, state, send, done) => { + explodes: (state, data, send, done) => { setTimeout(() => done(new Error('effect error')), 5) } } diff --git a/tests/browser/routing.js b/tests/browser/routing.js index b1b12a95..4ef2c17b 100644 --- a/tests/browser/routing.js +++ b/tests/browser/routing.js @@ -6,7 +6,7 @@ const view = require('../../html') test('routing', function (t) { t.test('history', function (t) { - t.plan(3) + t.plan(2) const history = Event() const choo = proxyquire('../..', { @@ -20,11 +20,11 @@ test('routing', function (t) { user: null }, reducers: { - set: (action, state) => ({user: action.id}) + set: (state, data) => ({user: data.id}) }, effects: { - open: function (action, state, send, done) { - t.deepEqual(action, {id: 1}) + open: function (state, data, send, done) { + t.deepEqual(data, {id: 1}) send('set', {id: 1}, function (err) { if (err) return done(err) history.broadcast('/users/1') @@ -75,10 +75,10 @@ test('routing', function (t) { // user: null // }, // reducers: { - // set: (action, state) => ({user: action.id}) + // set: (state, data) => ({user: action.id}) // }, // effects: { - // open: function (action, state, send, done) { + // open: function (state, data, send, done) { // send('set', {id: 1}, function (err) { // if (err) return done(err) // hash.broadcast('#users/1')