Skip to content

Commit

Permalink
Fixes immutable util for subsequent mutations
Browse files Browse the repository at this point in the history
  • Loading branch information
goatslacker committed Apr 27, 2015
1 parent 34989b8 commit a0d32c5
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 14 deletions.
17 changes: 15 additions & 2 deletions dist/alt-with-addons.js
Expand Up @@ -1099,6 +1099,7 @@ var AltStore = (function () {
this[LIFECYCLE] = {};
this[STATE_CONTAINER] = state || model;

this._storeName = model._storeName;
this.boundListeners = model[ALL_LISTENERS];
this.StoreModel = StoreModel;
if (typeof this.StoreModel === 'object') {
Expand Down Expand Up @@ -1173,7 +1174,7 @@ var AltStore = (function () {
}, {
key: 'getState',
value: function getState() {
return this.StoreModel.config.getState(this[STATE_CONTAINER]);
return this.StoreModel.config.getState.call(this, this[STATE_CONTAINER]);
}
}]);

Expand Down Expand Up @@ -1543,6 +1544,16 @@ var Alt = (function () {
store.emitChange();
});
}
}, {
key: 'prepare',
value: function prepare(store, payload) {
var data = {};
if (!store._storeName) {
throw new ReferenceError('Store provided does not have a name');
}
data[store._storeName] = payload;
return this.serialize(data);
}
}, {
key: 'addActions',

Expand Down Expand Up @@ -1882,9 +1893,11 @@ function doSetState(store, storeInstance, state) {
return;
}

var config = storeInstance.StoreModel.config;

var nextState = typeof state === 'function' ? state(storeInstance[STATE_CONTAINER]) : state;

storeInstance[STATE_CONTAINER] = storeInstance.StoreModel.config.setState(storeInstance[STATE_CONTAINER], nextState);
storeInstance[STATE_CONTAINER] = config.setState.call(store, storeInstance[STATE_CONTAINER], nextState);

if (!store.alt.dispatcher.isDispatching()) {
store.emitChange();
Expand Down
17 changes: 15 additions & 2 deletions dist/alt.js
Expand Up @@ -819,6 +819,7 @@ var AltStore = (function () {
this[LIFECYCLE] = {};
this[STATE_CONTAINER] = state || model;

this._storeName = model._storeName;
this.boundListeners = model[ALL_LISTENERS];
this.StoreModel = StoreModel;
if (typeof this.StoreModel === 'object') {
Expand Down Expand Up @@ -893,7 +894,7 @@ var AltStore = (function () {
}, {
key: 'getState',
value: function getState() {
return this.StoreModel.config.getState(this[STATE_CONTAINER]);
return this.StoreModel.config.getState.call(this, this[STATE_CONTAINER]);
}
}]);

Expand Down Expand Up @@ -1203,9 +1204,11 @@ function doSetState(store, storeInstance, state) {
return;
}

var config = storeInstance.StoreModel.config;

var nextState = typeof state === 'function' ? state(storeInstance[STATE_CONTAINER]) : state;

storeInstance[STATE_CONTAINER] = storeInstance.StoreModel.config.setState(storeInstance[STATE_CONTAINER], nextState);
storeInstance[STATE_CONTAINER] = config.setState.call(store, storeInstance[STATE_CONTAINER], nextState);

if (!store.alt.dispatcher.isDispatching()) {
store.emitChange();
Expand Down Expand Up @@ -1712,6 +1715,16 @@ var Alt = (function () {
store.emitChange();
});
}
}, {
key: 'prepare',
value: function prepare(store, payload) {
var data = {};
if (!store._storeName) {
throw new ReferenceError('Store provided does not have a name');
}
data[store._storeName] = payload;
return this.serialize(data);
}
}, {
key: 'addActions',

Expand Down
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -179,6 +179,7 @@
"no-new-object": [
2
],
"no-return-assign": 0,
"no-sequences": [
0
],
Expand Down
2 changes: 1 addition & 1 deletion src/alt/AltStore.js
Expand Up @@ -85,6 +85,6 @@ export default class AltStore {
}

getState() {
return this.StoreModel.config.getState(this[STATE_CONTAINER])
return this.StoreModel.config.getState.call(this, this[STATE_CONTAINER])
}
}
5 changes: 4 additions & 1 deletion src/alt/utils/StoreUtils.js
Expand Up @@ -18,11 +18,14 @@ function doSetState(store, storeInstance, state) {
return
}

const { config } = storeInstance.StoreModel

const nextState = typeof state === 'function'
? state(storeInstance[STATE_CONTAINER])
: state

storeInstance[STATE_CONTAINER] = storeInstance.StoreModel.config.setState(
storeInstance[STATE_CONTAINER] = config.setState.call(
store,
storeInstance[STATE_CONTAINER],
nextState
)
Expand Down
2 changes: 1 addition & 1 deletion src/utils/ImmutableUtil.js
Expand Up @@ -43,7 +43,7 @@ function immutable(store) {
stateKey: 'state',

setState(currentState, nextState) {
return nextState
return (this.state = nextState)
},

getState(currentState) {
Expand Down
90 changes: 83 additions & 7 deletions test/immutable-stores.js
Expand Up @@ -17,35 +17,111 @@ export default {
'normal stores'() {
const alt = new Alt()

const action = alt.generateActions('addY')
const action = alt.generateActions('addY', 'addX')

const store1 = alt.createStore(immutable({
displayName: 'ImmutableStore',
bindListeners: { addY: action.addY },
bindListeners: { addY: action.addY, addX: action.addX },
state: Immutable.Map({ x: 1 }),
addY() {
this.setState(this.state.set('y', 2))
},
addX() {
this.setState(this.state.set('x', 5))
}
}))

const store2 = alt.createStore({
displayName: 'MutableStore',
bindListeners: { addY: action.addY },
bindListeners: { addY: action.addY, addX: action.addX },
state: { x: 1 },
addY() {
this.setState({ y: 2 })
},
addX() {
this.setState({ x: 5 })
}
})

assert(store1.getState().toJS().x === 1)
assert(store2.getState().x === 1)

action.addY()
assert(store1.getState().toJS().x === 1, 'store1 x was not replaced')
assert(store2.getState().x === 1, 'store2 x was not replaced')
assert(store1.getState().toJS().y === 2, 'new y exists in store1')
assert(store2.getState().y === 2, 'new y exists in store2')

assert(store1.getState().toJS().x === 1)
assert(store2.getState().x === 1, 'store2 state was not replaced')
assert(store1.getState().toJS().y === 2)
assert(store2.getState().y === 2, 'new state exists')
action.addX()
assert(store1.getState().toJS().x === 5, 'new x exists in store1')
assert(store2.getState().x === 5, 'new x exists in store2')

assert(store1.getState().toJS().y === 2, 'store1 y was not replaced')
assert(store2.getState().y === 2, 'store2 y was not replaced')

// fire it again to make sure state is not blown away
action.addY()

assert(store1.getState().toJS().x === 5, 'store1 x remains 5')
assert(store2.getState().x === 5, 'store2 state remains 5')
assert(store1.getState().toJS().y === 2, 'store1 y value has been updated')
assert(store2.getState().y === 2, 'store2 y value has been updated')
},

'nested immutable structures'() {
const alt = new Alt()

const actions = alt.generateActions('replaceMap', 'replaceList', 'updateBar')

@immutable
class ImmutableStore {
constructor() {
this.bindListeners({
handleUpdateBar: actions.updateBar,
handleReplaceMap: actions.replaceMap,
handleReplaceList: actions.replaceList
})

this.state = Immutable.Map({
bar: 'hello',
list: Immutable.List([]),
map: Immutable.Map({})
})
}

handleUpdateBar(x) {
this.setState(this.state.set('bar', x))
}

handleReplaceMap(x) {
this.setState(this.state.set('map', Immutable.fromJS(x).toMap()))
}

handleReplaceList(x) {
this.setState(this.state.set('list', Immutable.fromJS(x).toList()))
}
}

const store = alt.createStore(ImmutableStore, 'ImmutableStore')

assert(store.getState().get('bar') === 'hello', 'bar is initially `hello`')
assert(store.getState().get('map').count() === 0, 'map is initially zero')
assert(store.getState().get('list').count() === 0, 'list is initially zero')

actions.replaceMap({a: 1, b: 2})
assert(store.getState().get('bar') === 'hello', 'bar is still `hello` after replacing map')
assert(store.getState().get('list').count() === 0, 'list still has zero items after replacing map')
assert(store.getState().get('map').count() === 2, 'map has 2 items in it now after replacing map')

actions.replaceList([1, 2, 3, 4])
assert(store.getState().get('bar') === 'hello', 'bar is still `hello` after replacing list')
assert(store.getState().get('list').count() === 4, 'list has 4 items now after replacing list')
assert(store.getState().get('map').count() === 2, 'map still has 2 items in it after replacing list')

actions.updateBar('world')
assert(store.getState().get('bar') === 'world', 'bar is now `world` after updating bar')
assert(store.getState().get('list').count() === 4, 'list still has 4 items after updating bar')
assert(store.getState().get('map').count() === 2, 'map still has 2 items in it after updating bar')
},

'using list'() {
Expand Down

0 comments on commit a0d32c5

Please sign in to comment.