Fix redux support for observables (#275)

fixes #274
This commit is contained in:
Michael van Engelshoven 2016-05-09 03:45:26 +02:00 committed by Dan Abramov
parent ac3dc18391
commit 7b5adf9718
3 changed files with 53 additions and 9 deletions

View File

@ -54,15 +54,17 @@
"react-addons-test-utils": "^0.14.0", "react-addons-test-utils": "^0.14.0",
"react-dom": "^0.14.0", "react-dom": "^0.14.0",
"rimraf": "^2.3.4", "rimraf": "^2.3.4",
"rxjs": "^5.0.0-beta.6",
"webpack": "^1.11.0" "webpack": "^1.11.0"
}, },
"peerDependencies": { "peerDependencies": {
"redux": "^3.0.0", "redux": "^3.5.0",
"react": "^0.14.0 || ^15.0.0-rc.1" "react": "^0.14.0 || ^15.0.0-rc.1"
}, },
"dependencies": { "dependencies": {
"lodash": "^4.2.0", "lodash": "^4.2.0",
"react-redux": "^4.0.0", "react-redux": "^4.0.0",
"redux": "^3.2.1" "redux": "^3.5.2",
"symbol-observable": "^0.2.4"
} }
} }

View File

@ -1,5 +1,6 @@
import difference from 'lodash/difference'; import difference from 'lodash/difference';
import union from 'lodash/union'; import union from 'lodash/union';
import $$observable from 'symbol-observable';
export const ActionTypes = { export const ActionTypes = {
PERFORM_ACTION: 'PERFORM_ACTION', PERFORM_ACTION: 'PERFORM_ACTION',
@ -383,6 +384,14 @@ function unliftState(liftedState) {
function unliftStore(liftedStore, liftReducer) { function unliftStore(liftedStore, liftReducer) {
let lastDefinedState; let lastDefinedState;
function getState() {
const state = unliftState(liftedStore.getState());
if (state !== undefined) {
lastDefinedState = state;
}
return lastDefinedState;
}
return { return {
...liftedStore, ...liftedStore,
@ -393,16 +402,31 @@ function unliftStore(liftedStore, liftReducer) {
return action; return action;
}, },
getState() { getState,
const state = unliftState(liftedStore.getState());
if (state !== undefined) {
lastDefinedState = state;
}
return lastDefinedState;
},
replaceReducer(nextReducer) { replaceReducer(nextReducer) {
liftedStore.replaceReducer(liftReducer(nextReducer)); liftedStore.replaceReducer(liftReducer(nextReducer));
},
[$$observable]() {
return {
...liftedStore[$$observable](),
subscribe(observer) {
if (typeof observer !== 'object') {
throw new TypeError('Expected the observer to be an object.');
}
function observeState() {
if (observer.next) {
observer.next(getState());
}
}
observeState();
const unsubscribe = liftedStore.subscribe(observeState);
return { unsubscribe };
}
};
} }
}; };
} }

View File

@ -1,6 +1,9 @@
import expect, { spyOn } from 'expect'; import expect, { spyOn } from 'expect';
import { createStore, compose } from 'redux'; import { createStore, compose } from 'redux';
import instrument, { ActionCreators } from '../src/instrument'; import instrument, { ActionCreators } from '../src/instrument';
import {Observable} from 'rxjs';
import 'rxjs/add/observable/from';
function counter(state = 0, action) { function counter(state = 0, action) {
switch (action.type) { switch (action.type) {
@ -53,6 +56,21 @@ describe('instrument', () => {
expect(store.getState()).toBe(2); expect(store.getState()).toBe(2);
}); });
it('should provide observable', () => {
let lastValue;
let calls = 0;
Observable.from(store)
.subscribe(state => {
lastValue = state;
calls++;
});
expect(lastValue).toBe(0);
store.dispatch({ type: 'INCREMENT' });
expect(lastValue).toBe(1);
});
it('should rollback state to the last committed state', () => { it('should rollback state to the last committed state', () => {
store.dispatch({ type: 'INCREMENT' }); store.dispatch({ type: 'INCREMENT' });
store.dispatch({ type: 'INCREMENT' }); store.dispatch({ type: 'INCREMENT' });