From fff2d636847467aed98eabc2a82706957950bdee Mon Sep 17 00:00:00 2001 From: solsen Date: Fri, 19 Jan 2018 23:39:52 -0500 Subject: [PATCH] Improved looping; simplify assign --- README.md | 11 ++++++----- package.json | 7 ++++--- src/index.js | 27 ++++++++++----------------- src/integrations/preact.js | 6 +++--- src/integrations/react.js | 8 ++++---- src/util.js | 24 ++++++++++++------------ test/unistore.test.js | 2 +- 7 files changed, 40 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index f6a97dd..1e79fa1 100644 --- a/README.md +++ b/README.md @@ -69,10 +69,10 @@ You can find the library on `window.unistore`. import createStore from 'unistore' import { Provider, connect } from 'unistore/preact' -let store = createStore({ count: 0 }) +const store = createStore({ count: 0 }) // If actions is a function, it gets passed the store: -let actions = store => ({ +const actions = store => ({ // Actions can just return a state update: increment(state) { return { count: state.count+1 } @@ -90,7 +90,7 @@ let actions = store => ({ // Async actions can be pure async/promise functions: async getStuff(state) { - let res = await fetch('/foo.json') + const res = await fetch('/foo.json') return { stuff: await res.json() } }, @@ -126,8 +126,8 @@ Make sure to have [Redux devtools extension](https://github.com/zalmoxisus/redux import createStore from 'unistore' import devtools from 'unistore/devtools' -let initialState = { count: 0 }; -let store = process.env.NODE_ENV === 'production' ? createStore(initialState) : devtools(createStore(initialState)); +const initialState = { count: 0 }; +const store = process.env.NODE_ENV === 'production' ? createStore(initialState) : devtools(createStore(initialState)); // ... ``` @@ -150,4 +150,5 @@ If not, just open a [new clear and descriptive issue](../../issues/new). [MIT License](https://oss.ninja/mit/developit) © [Jason Miller](https://jasonformat.com) [preact]: https://github.com/developit/preact + [react]: https://github.com/facebook/react diff --git a/package.json b/package.json index e104d37..7dd1f7b 100644 --- a/package.json +++ b/package.json @@ -10,12 +10,13 @@ "scripts": { "build": "npm-run-all --silent -p build:main build:integrations build:combined -s size docs", "build:main": "microbundle", - "build:integrations": "microbundle src/integrations/*.js -o x.js -f cjs", - "build:combined": "microbundle src/combined/*.js -o full/x.js", + "build:integrations": "microbundle \"src/integrations/*.js\" -o x.js -f cjs", + "build:combined": "microbundle \"src/combined/*.js\" -o full/x.js", "size": "strip-json-comments --no-whitespace dist/unistore.js | gzip-size && bundlesize", "docs": "documentation readme unistore.js -q --section API && npm run -s fixreadme", "fixreadme": "node -e 'var fs=require(\"fs\");fs.writeFileSync(\"README.md\", fs.readFileSync(\"README.md\", \"utf8\").replace(/^- /gm, \"- \"))'", "test": "eslint src && npm run build && jest", + "test:jest": "jest", "prepare": "npm t", "release": "npm t && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish" }, @@ -89,7 +90,7 @@ "eslint-config-developit": "^1.1.1", "gzip-size-cli": "^2.1.0", "jest": "^21.2.1", - "microbundle": "^0.2.4", + "microbundle": "^0.3.1", "npm-run-all": "^4.1.2", "preact": "^8.2.6", "strip-json-comments-cli": "^1.0.1" diff --git a/src/index.js b/src/index.js index 2e50188..b26ce33 100644 --- a/src/index.js +++ b/src/index.js @@ -11,26 +11,18 @@ import { assign } from './util'; * store.setState({ c: 'd' }); // logs { a: 'b', c: 'd' } */ export default function createStore(state) { - let listeners = []; + const listeners = []; state = state || {}; function unsubscribe(listener) { - let out = []; - for (let i=0; i -1) listeners.splice(i, 1); } function setState(update, overwrite, action) { - state = overwrite ? update : assign(assign({}, state), update); - let currentListeners = listeners; - for (let i=0; i 0) listeners[i](state, action); } /** An observable state container, returned from {@link createStore} @@ -52,9 +44,10 @@ export default function createStore(state) { // Note: perf tests verifying this implementation: https://esbench.com/bench/5a295e6299634800a0349500 return function() { - let args = [state]; - for (let i=0; i { function Wrapper(props, { store }) { let state = mapStateToProps(store ? store.getState() : {}, props); - let boundActions = actions ? mapActions(actions, store) : { store }; - let update = () => { + const boundActions = actions ? mapActions(actions, store) : { store }; + const update = () => { let mapped = mapStateToProps(store ? store.getState() : {}, this.props); for (let i in mapped) if (mapped[i]!==state[i]) { state = mapped; @@ -40,7 +40,7 @@ export function connect(mapStateToProps, actions) { this.componentWillUnmount = () => { store.unsubscribe(update); }; - this.render = props => h(Child, assign(assign(assign({}, boundActions), props), state)); + this.render = props => h(Child, assign({}, boundActions, props, state)); } return (Wrapper.prototype = new Component()).constructor = Wrapper; }; diff --git a/src/integrations/react.js b/src/integrations/react.js index b499a00..9a4b9c8 100644 --- a/src/integrations/react.js +++ b/src/integrations/react.js @@ -27,9 +27,9 @@ export function connect(mapStateToProps, actions) { Component.call(this, props, context); let { store } = context; let state = mapStateToProps(store ? store.getState() : {}, props); - let boundActions = actions ? mapActions(actions, store) : { store }; - let update = () => { - let mapped = mapStateToProps(store ? store.getState() : {}, this.props); + const boundActions = actions ? mapActions(actions, store) : { store }; + const update = () => { + const mapped = mapStateToProps(store ? store.getState() : {}, this.props); for (let i in mapped) if (mapped[i]!==state[i]) { state = mapped; return this.forceUpdate(); @@ -46,7 +46,7 @@ export function connect(mapStateToProps, actions) { this.componentWillUnmount = () => { store.unsubscribe(update); }; - this.render = () => createElement(Child, assign(assign(assign({}, boundActions), this.props), state)); + this.render = () => createElement(Child, assign({}, boundActions, this.props, state)); } Wrapper.contextTypes = CONTEXT_TYPES; return (Wrapper.prototype = Object.create(Component)).constructor = Wrapper; diff --git a/src/util.js b/src/util.js index 7050423..aeb0f73 100644 --- a/src/util.js +++ b/src/util.js @@ -1,10 +1,8 @@ // Bind an object/factory of actions to the store and wrap them. export function mapActions(actions, store) { if (typeof actions==='function') actions = actions(store); - let mapped = {}; - for (let i in actions) { - mapped[i] = store.action(actions[i]); - } + const mapped = {}; + for (let i in actions) mapped[i] = store.action(actions[i]); return mapped; } @@ -13,17 +11,19 @@ export function mapActions(actions, store) { export function select(properties) { if (typeof properties==='string') properties = properties.split(/\s*,\s*/); return state => { - let selected = {}; - for (let i=0; i 0) selected[properties[i]] = state[properties[i]]; return selected; }; } -// Lighter Object.assign stand-in -export function assign(obj, props) { - for (let i in props) obj[i] = props[i]; - return obj; +// Lighter Object.assign clone +export function assign(_) { + for (let i = 1; i { let sub1 = jest.fn(); let sub2 = jest.fn(); - let action = undefined; + let action; let rval = store.subscribe(sub1); expect(rval).toBeInstanceOf(Function);