diff --git a/src/dispatchOn.js b/src/dispatchOn.js
new file mode 100644
index 0000000..7141d59
--- /dev/null
+++ b/src/dispatchOn.js
@@ -0,0 +1,70 @@
+import React, { Component, PropTypes } from 'react';
+import { Subscription } from 'rxjs/Subscription';
+
+const $$reduxObservableSubscription = '@@reduxObservableSubscription';
+
+const dispatchFactories = (subscription, store, factories, args) => {
+ factories.map(factory => store.dispatch(factory(...args)))
+ .forEach(sub => sub && subscription.add(sub));
+};
+
+export function dispatchOn({
+ willMount = null,
+ mount = null,
+ update = null,
+ willRecieveProps = null
+}) {
+ return (ComposedComponent) =>
+ class DispatchOnMountComponent extends Component {
+ constructor(props) {
+ super(props);
+ }
+
+ static contextTypes = {
+ store: PropTypes.object.isRequired
+ }
+
+ getSubscription() {
+ const subscription = this[$$reduxObservableSubscription];
+ if (!subscription || subscription.isUnsubscribed) {
+ this[$$reduxObservableSubscription] = new Subscription();
+ }
+ return this[$$reduxObservableSubscription];
+ }
+
+ componentWillMount() {
+ if (willMount) {
+ dispatchFactories(this.getSubscription(), this.context.store, willMount, [this.props]);
+ }
+ }
+
+ componentDidMount() {
+ if (mount) {
+ dispatchFactories(this.getSubscription(), this.context.store, mount, [this.props]);
+ }
+ }
+
+ componentDidUpdate(prevProps) {
+ if (update) {
+ dispatchFactories(this.getSubscription(), this.context.store, update, [this.props, prevProps]);
+ }
+ }
+
+ componentWillReceiveProps(nextProps) {
+ if (willRecieveProps) {
+ dispatchFactories(this.getSubscription(), this.context.store, willRecieveProps, [this.props, nextProps]);
+ }
+ }
+
+ componentWillUnmount() {
+ const subscription = this[$$reduxObservableSubscription];
+ if (subscription) {
+ subscription.unsubscribe();
+ }
+ }
+
+ render() {
+ return ();
+ }
+ };
+}
diff --git a/src/dispatchOnMount.js b/src/dispatchOnMount.js
deleted file mode 100644
index 65f30de..0000000
--- a/src/dispatchOnMount.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import React, { Component, PropTypes } from 'react';
-import { Subscription } from 'rxjs/Subscription';
-
-const $$reduxObservableSubscription = '@@reduxObservableSubscription';
-
-export function dispatchOnMount(...factories) {
- return (ComposedComponent) =>
- class DispatchOnMountComponent extends Component {
- static contextTypes = {
- store: PropTypes.object.isRequired
- }
-
- componentDidMount() {
- this[$$reduxObservableSubscription] = new Subscription();
- factories.map(factory => this.context.store.dispatch(factory(this.props)))
- .forEach(sub => sub && this[$$reduxObservableSubscription].add(sub));
- }
-
- componentWillUnmount() {
- this[$$reduxObservableSubscription].unsubscribe();
- }
-
- render() {
- return ();
- }
- };
-}
diff --git a/src/index.js b/src/index.js
index 4c38f42..b196323 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1 +1 @@
-export { dispatchOnMount } from './dispatchOnMount';
+export { dispatchOn } from './dispatchOn';
diff --git a/test/dispatchOnMount-spec.js b/test/dipatchOn-spec.js
similarity index 58%
rename from test/dispatchOnMount-spec.js
rename to test/dipatchOn-spec.js
index c1cadd8..0a86b68 100644
--- a/test/dispatchOnMount-spec.js
+++ b/test/dipatchOn-spec.js
@@ -1,7 +1,7 @@
/* global describe, it */
import { expect } from 'chai';
import { reduxObservable } from 'redux-observable';
-import { dispatchOnMount } from '../';
+import { dispatchOn } from '../';
import { Component } from 'react';
import { createStore, applyMiddleware } from 'redux';
import * as Rx from 'rxjs';
@@ -9,9 +9,29 @@ import 'babel-polyfill';
const { Observable } = Rx;
-describe('dispatchOnMount', () => {
+describe('dispatchOn', () => {
it('should exist', () => {
- expect(dispatchOnMount).to.be.a('function');
+ expect(dispatchOn).to.be.a('function');
+ });
+
+ it('should wire a thunkservable to dispatch on componentWillMount', () => {
+ let reducedActions = [];
+ let reducer = (state, action) => {
+ reducedActions.push(action);
+ return state;
+ };
+ let store = createStore(reducer, applyMiddleware(reduxObservable()));
+
+ @dispatchOn({ willMount: [() => () => Observable.of({ type: 'TEST' })] })
+ class TestComponent extends Component {
+ }
+
+ let comp = new TestComponent();
+ // fake connection?
+ comp.context = { store };
+ comp.componentWillMount();
+
+ expect(reducedActions).to.deep.equal([{ type: '@@redux/INIT' }, { type: 'TEST' }]);
});
it('should wire a thunkservable to dispatch on componentDidMount', () => {
@@ -22,7 +42,7 @@ describe('dispatchOnMount', () => {
};
let store = createStore(reducer, applyMiddleware(reduxObservable()));
- @dispatchOnMount(() => () => Observable.of({ type: 'TEST' }))
+ @dispatchOn({ mount: [() => () => Observable.of({ type: 'TEST' })] })
class TestComponent extends Component {
}
@@ -34,6 +54,65 @@ describe('dispatchOnMount', () => {
expect(reducedActions).to.deep.equal([{ type: '@@redux/INIT' }, { type: 'TEST' }]);
});
+ it('should wire a thunkservable to dispatch on componentDidUpdate', () => {
+ let reducedActions = [];
+ let reducer = (state, action) => {
+ reducedActions.push(action);
+ return state;
+ };
+ let store = createStore(reducer, applyMiddleware(reduxObservable()));
+ let _prevProps;
+ let _thisProps;
+
+ @dispatchOn({ update: [(thisProps, prevProps) => {
+ _thisProps = thisProps;
+ _prevProps = prevProps;
+ return () => Observable.of({ type: 'TEST' });
+ }] })
+ class TestComponent extends Component {
+ }
+
+ let comp = new TestComponent();
+ // fake connection?
+ comp.context = { store };
+ comp.props = { some: 'props' };
+ comp.componentDidUpdate({ prev: 'props' });
+
+ expect(_thisProps).to.deep.equal({ some: 'props' });
+ expect(_prevProps).to.deep.equal({ prev: 'props' });
+ expect(reducedActions).to.deep.equal([{ type: '@@redux/INIT' }, { type: 'TEST' }]);
+ });
+
+ it('should wire a thunkservable to dispatch on componentWillReceiveProps', () => {
+ let reducedActions = [];
+ let reducer = (state, action) => {
+ reducedActions.push(action);
+ return state;
+ };
+ let store = createStore(reducer, applyMiddleware(reduxObservable()));
+
+ let _thisProps;
+ let _nextProps;
+
+ @dispatchOn({ willRecieveProps: [(thisProps, nextProps) => {
+ _thisProps = thisProps;
+ _nextProps = nextProps;
+ return () => Observable.of({ type: 'TEST' });
+ }] })
+ class TestComponent extends Component {
+ }
+
+ let comp = new TestComponent();
+ // fake connection?
+ comp.context = { store };
+ comp.props = { some: 'props' };
+ comp.componentWillReceiveProps({ next: 'props' });
+
+ expect(_thisProps).to.deep.equal({ some: 'props' });
+ expect(_nextProps).to.deep.equal({ next: 'props' });
+ expect(reducedActions).to.deep.equal([{ type: '@@redux/INIT' }, { type: 'TEST' }]);
+ });
+
it('should unsubscribe on componentWillUnmount', () => {
let reducedActions = [];
let reducer = (state, action) => {
@@ -56,7 +135,10 @@ describe('dispatchOnMount', () => {
};
});
- @dispatchOnMount(() => () => source1, () => () => source2)
+ @dispatchOn({ mount: [
+ () => () => source1,
+ () => () => source2
+ ] })
class TestComponent extends Component {
}
@@ -85,7 +167,10 @@ describe('dispatchOnMount', () => {
let source1 = Observable.of({ type: 'SOURCE1' });
let source2 = Observable.of({ type: 'SOURCE2' });
- @dispatchOnMount(() => () => source1, () => () => source2)
+ @dispatchOn({ mount: [
+ () => () => source1,
+ () => () => source2
+ ] })
class TestComponent extends Component {
}
@@ -111,7 +196,7 @@ describe('dispatchOnMount', () => {
let source2 = Observable.of({ type: 'SOURCE2' });
- @dispatchOnMount(() => ({ type: 'PLAIN_ACTION' }), () => () => source2)
+ @dispatchOn({ mount: [() => ({ type: 'PLAIN_ACTION' }), () => () => source2] })
class TestComponent extends Component {
}
@@ -139,9 +224,12 @@ describe('dispatchOnMount', () => {
};
let store = createStore(reducer, applyMiddleware(reduxObservable()));
- @dispatchOnMount(
- (props) => ({ type: 'PLAIN_ACTION', value: props.value }),
- (props) => () => Observable.of({ type: 'SOURCE2', value: props.value }))
+ @dispatchOn({
+ mount: [
+ (props) => ({ type: 'PLAIN_ACTION', value: props.value }),
+ (props) => () => Observable.of({ type: 'SOURCE2', value: props.value })
+ ]
+ })
class TestComponent extends Component {
}