Skip to content

Commit 7b5adf9

Browse files
micha149gaearon
authored andcommitted
Fix redux support for observables (#275)
fixes #274
1 parent ac3dc18 commit 7b5adf9

File tree

3 files changed

+53
-9
lines changed

3 files changed

+53
-9
lines changed

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,17 @@
5454
"react-addons-test-utils": "^0.14.0",
5555
"react-dom": "^0.14.0",
5656
"rimraf": "^2.3.4",
57+
"rxjs": "^5.0.0-beta.6",
5758
"webpack": "^1.11.0"
5859
},
5960
"peerDependencies": {
60-
"redux": "^3.0.0",
61+
"redux": "^3.5.0",
6162
"react": "^0.14.0 || ^15.0.0-rc.1"
6263
},
6364
"dependencies": {
6465
"lodash": "^4.2.0",
6566
"react-redux": "^4.0.0",
66-
"redux": "^3.2.1"
67+
"redux": "^3.5.2",
68+
"symbol-observable": "^0.2.4"
6769
}
6870
}

src/instrument.js

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import difference from 'lodash/difference';
22
import union from 'lodash/union';
3+
import $$observable from 'symbol-observable';
34

45
export const ActionTypes = {
56
PERFORM_ACTION: 'PERFORM_ACTION',
@@ -383,6 +384,14 @@ function unliftState(liftedState) {
383384
function unliftStore(liftedStore, liftReducer) {
384385
let lastDefinedState;
385386

387+
function getState() {
388+
const state = unliftState(liftedStore.getState());
389+
if (state !== undefined) {
390+
lastDefinedState = state;
391+
}
392+
return lastDefinedState;
393+
}
394+
386395
return {
387396
...liftedStore,
388397

@@ -393,16 +402,31 @@ function unliftStore(liftedStore, liftReducer) {
393402
return action;
394403
},
395404

396-
getState() {
397-
const state = unliftState(liftedStore.getState());
398-
if (state !== undefined) {
399-
lastDefinedState = state;
400-
}
401-
return lastDefinedState;
402-
},
405+
getState,
403406

404407
replaceReducer(nextReducer) {
405408
liftedStore.replaceReducer(liftReducer(nextReducer));
409+
},
410+
411+
[$$observable]() {
412+
return {
413+
...liftedStore[$$observable](),
414+
subscribe(observer) {
415+
if (typeof observer !== 'object') {
416+
throw new TypeError('Expected the observer to be an object.');
417+
}
418+
419+
function observeState() {
420+
if (observer.next) {
421+
observer.next(getState());
422+
}
423+
}
424+
425+
observeState();
426+
const unsubscribe = liftedStore.subscribe(observeState);
427+
return { unsubscribe };
428+
}
429+
};
406430
}
407431
};
408432
}

test/instrument.spec.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import expect, { spyOn } from 'expect';
22
import { createStore, compose } from 'redux';
33
import instrument, { ActionCreators } from '../src/instrument';
4+
import {Observable} from 'rxjs';
5+
6+
import 'rxjs/add/observable/from';
47

58
function counter(state = 0, action) {
69
switch (action.type) {
@@ -53,6 +56,21 @@ describe('instrument', () => {
5356
expect(store.getState()).toBe(2);
5457
});
5558

59+
it('should provide observable', () => {
60+
let lastValue;
61+
let calls = 0;
62+
63+
Observable.from(store)
64+
.subscribe(state => {
65+
lastValue = state;
66+
calls++;
67+
});
68+
69+
expect(lastValue).toBe(0);
70+
store.dispatch({ type: 'INCREMENT' });
71+
expect(lastValue).toBe(1);
72+
});
73+
5674
it('should rollback state to the last committed state', () => {
5775
store.dispatch({ type: 'INCREMENT' });
5876
store.dispatch({ type: 'INCREMENT' });

0 commit comments

Comments
 (0)