diff --git a/README.md b/README.md index 89edb4a..7bb93ca 100644 --- a/README.md +++ b/README.md @@ -229,7 +229,7 @@ this.mapStores([ keys: ['foo', 'status'] }, { store: StoreFour, - altState: state => state + altState: storeState, state, props => storeState } ]); ``` @@ -248,22 +248,20 @@ class MyComponent extends Vlow.Component.extend(React.PureComponent) { } ``` - ### Using altState Sometimes you want to listen to state changes in a store but then do something with this state instead of just applying the state to a component. -This can be done by using an `altState(state)` hook which -will be triggered on state changes in the store but before the component state +This can be done by using an `altState(storeState, state, props)` hook which +will be triggered on state changes in the store but *before* the component state is changed. The `altState` function should return the state changes you want to make or `null` in case you don't want to update the state of the component. ```javascript -this.mapStore({store: ExampleStore, alState: (state) => { - // The `state` is received from the store. This is not the - // components state. This function should return the state - // you want to apply on `this` component. The function can +function altState(storeState, state, props) { + // This function should return the state + // you want to apply on the component. The function can // also return `null` in which case the components state // will not be changed. - if (this.props.status === 'error') { + if (props.status === 'error') { // the components state will not be changed return null; } @@ -271,8 +269,14 @@ this.mapStore({store: ExampleStore, alState: (state) => { // Other components still receive the `original` state // from the store. return { - items: state.items.filter(i => i.age > this.state.minAge) + items: storeState.items.filter(i => i.age > state.minAge) }; -}}); +} + +// Use the altState function +const stores = { + store: MyStore, + altState, +}; ``` diff --git a/lib/index.js b/lib/index.js index 25a430f..a4a0911 100644 --- a/lib/index.js +++ b/lib/index.js @@ -61,7 +61,7 @@ var _withVlow = _interopRequireDefault(require("./withVlow")); * SOFTWARE. */ var Vlow = { - version: '1.1.2' + version: '1.1.4' }; Vlow.Store = _store.default; Vlow.Component = _component.default; diff --git a/lib/store.js b/lib/store.js index a392dfa..0d6de06 100644 --- a/lib/store.js +++ b/lib/store.js @@ -85,11 +85,10 @@ function () { }, { key: "_vlowSetState", value: function _vlowSetState(listener, state, counter) { - state = !listener.keys ? !listener.altState ? state : listener.altState(this.state) || {} : this._vlowFilterState(state, listener.keys); + var component = listener.component; + state = !listener.keys ? !listener.altState ? state : listener.altState(this.state, component.state, component.props) || {} : this._vlowFilterState(state, listener.keys); if (Object.keys(state).length) { - var component = listener.component; - switch (component._vlowState_) { case _states.default.init: counter ? process.env.NODE_ENV !== 'production' ? (0, _invariant.default)(false, 'Store `%s` is using `setState()` with a callback on component `%s` which is not yet mounted. This is not possible, make sure all components are mounted or remove the callback from setState.', this.constructor.name, component.constructor.name) : (0, _invariant.default)(false) : undefined; diff --git a/package-lock.json b/package-lock.json index 2ae3163..1707bbd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "vlow", - "version": "1.1.3", + "version": "1.1.4", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -3280,14 +3280,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3302,20 +3300,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -3432,8 +3427,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -3445,7 +3439,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -3460,7 +3453,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -3468,14 +3460,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.2.4", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.1", "yallist": "^3.0.0" @@ -3494,7 +3484,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -3575,8 +3564,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -3588,7 +3576,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -3710,7 +3697,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", diff --git a/package.json b/package.json index add8673..efc75a7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vlow", - "version": "1.1.3", + "version": "1.1.4", "description": "A simple library for unidirectional dataflow architecture inspired by Reflux", "main": "lib/index.js", "scripts": { diff --git a/src/index.js b/src/index.js index ccd7255..4379f15 100644 --- a/src/index.js +++ b/src/index.js @@ -25,7 +25,7 @@ import {createActions} from './actions'; import withVlow from './withVlow'; const Vlow = { - version: '1.1.2', + version: '1.1.4', }; Vlow.Store = Store; diff --git a/src/store.js b/src/store.js index 8554864..113b921 100644 --- a/src/store.js +++ b/src/store.js @@ -48,10 +48,10 @@ class Store { } _vlowSetState(listener, state, counter) { - state = !listener.keys ? !listener.altState ? state : listener.altState(this.state) || {} : this._vlowFilterState(state, listener.keys); + const component = listener.component; + state = !listener.keys ? !listener.altState ? state : listener.altState(this.state, component.state, component.props) || {} : this._vlowFilterState(state, listener.keys); if (Object.keys(state).length) { - const component = listener.component; switch (component._vlowState_) { case States.init: counter ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Store `%s` is using `setState()` with a callback on component `%s` which is not yet mounted. This is not possible, make sure all components are mounted or remove the callback from setState.', this.constructor.name, component.constructor.name) : invariant(false) : undefined; diff --git a/test.js b/test.js index 8d01bfe..35dab07 100644 --- a/test.js +++ b/test.js @@ -213,10 +213,12 @@ describe('Test alter state', () => { class Component extends Vlow.Component.extend(FakeReactComponent) { constructor(props) { super(props); - this.mapStore({store: TestStore, altState: (state) => { - return !state ? null : { - items: state.items, - len: state.items.length + this.mapStore({store: TestStore, altState: (storeState, state, props) => { + assert(state === this.state, '`state` must be equal to the components state.'); + assert(props === this.props, '`props` must be equal to the components props.'); + return !storeState ? null : { + items: storeState.items, + len: storeState.items.length }; }}); }