Permalink
Browse files

feat(ofType): Better support for redux-actions (#348)

The actionCreators you make with redux-actions implement their own
toString, which means you don't have to keep track of action types at
all. Before this commit, you need to:

```
ofType(myActionCreator.toString())
```

In order to get this to work as expected. As of this commit, you can:

```
ofType(myActionCreator)
```
  • Loading branch information...
theengineear authored and jayphelps committed Oct 31, 2017
1 parent 579bd06 commit c4d0ccf2e01db9cc10532e5c4ab25fdabfa0a35d
Showing with 72 additions and 2 deletions.
  1. +6 −2 src/operators.js
  2. +66 −0 test/operators-spec.js
@@ -1,14 +1,18 @@
import { filter } from 'rxjs/operator/filter';

const keyHasType = (type, key) => {
return type === key || typeof key === 'function' && type === key.toString();
};

export function ofType(...keys) {
return function ofTypeOperatorFunction(source) {
return source::filter(({ type }) => {
const len = keys.length;
if (len === 1) {
return type === keys[0];
return keyHasType(type, keys[0]);
} else {
for (let i = 0; i < len; i++) {
if (keys[i] === type) {
if (keyHasType(type, keys[i])) {
return true;
}
}
@@ -52,5 +52,71 @@ describe('operators', () => {
expect(lulz).to.deep.equal([{ type: 'LULZ', i: 0 }, { type: 'LARF', i: 1 }]);
expect(haha).to.deep.equal([{ type: 'HAHA', i: 0 }]);
});

it('should handle actionCreators which define a toString method', () => {
// This helps when using the popular `redux-actions` npm package.
const actions = new Subject();
const cache1 = [];
const cache2 = [];
const LULZ_TYPE = 'LULZ';
const HAHA_TYPE = 'HAHA';
const LARF_TYPE = Symbol();

const createActionCreator = type => {
const actionCreator = payload => ({ type, payload });
actionCreator.toString = () => type;
return actionCreator;
};

const lulz = createActionCreator(LULZ_TYPE);
const haha = createActionCreator(HAHA_TYPE);
const larf = createActionCreator(LARF_TYPE);

// Sanity check.
expect(String(lulz)).to.deep.equal(LULZ_TYPE);
expect(lulz(0)).to.deep.equal({ type: LULZ_TYPE, payload: 0 });

actions.pipe(ofType(lulz, larf)).subscribe(x => cache1.push(x));
actions.pipe(ofType(haha)).subscribe(x => cache2.push(x));

actions.next(lulz(0));
expect(cache1).to.deep.equal([lulz(0)]);
expect(cache2).to.deep.equal([]);

actions.next(larf(1));
expect(cache1).to.deep.equal([lulz(0), larf(1)]);
expect(cache2).to.deep.equal([]);

actions.next(haha(0));
expect(cache1).to.deep.equal([lulz(0), larf(1)]);
expect(cache2).to.deep.equal([haha(0)]);
});

it('should not fail when types are symbols', () => {
const actions = new Subject();
const cache1 = [];
const cache2 = [];
const LULZ_TYPE = Symbol();
const HAHA_TYPE = Symbol();
const LARF_TYPE = Symbol();

actions.pipe(ofType(LULZ_TYPE, LARF_TYPE)).subscribe(x => cache1.push(x));
actions.pipe(ofType(HAHA_TYPE)).subscribe(x => cache2.push(x));

actions.next({ type: LULZ_TYPE, i: 0 });

expect(cache1).to.deep.equal([{ type: LULZ_TYPE, i: 0 }]);
expect(cache2).to.deep.equal([]);

actions.next({ type: LARF_TYPE, i: 1 });

expect(cache1).to.deep.equal([{ type: LULZ_TYPE, i: 0 }, { type: LARF_TYPE, i: 1 }]);
expect(cache2).to.deep.equal([]);

actions.next({ type: HAHA_TYPE, i: 0 });

expect(cache1).to.deep.equal([{ type: LULZ_TYPE, i: 0 }, { type: LARF_TYPE, i: 1 }]);
expect(cache2).to.deep.equal([{ type: HAHA_TYPE, i: 0 }]);
});
});
});

0 comments on commit c4d0ccf

Please sign in to comment.