Skip to content

Commit e6a6638

Browse files
committed
Merge pull request #2 from wbuchwalter/bc-1.0.0
Breaking changes
2 parents 7ddf9a6 + 665474f commit e6a6638

File tree

8 files changed

+122
-148
lines changed

8 files changed

+122
-148
lines changed

examples/counter/containers/CounterApp.ts

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {Component, View, onInit, onDestroy} from 'angular2/angular2';
22
import {bindActionCreators} from 'redux';
33
import {Counter} from '../components/Counter';
44
import * as CounterActions from '../actions/CounterActions';
5-
import Connector from '../redux/connector';
5+
import Connector from '../redux/connector';
66
import { Inject } from 'angular2/di';
77

88
@Component({
@@ -11,28 +11,29 @@ import { Inject } from 'angular2/di';
1111
bindings: []
1212
})
1313
@View({
14-
directives: [ Counter ],
14+
directives: [Counter],
1515
template: `
1616
<counter [counter]="counter" [actions]="actions"></counter>
1717
`
1818
})
1919
export class CounterApp {
20-
actions: any;
21-
unsubscribe: Function;
22-
counter;
23-
_ngRedux;
24-
25-
constructor(@Inject('ngRedux') ngRedux) {
26-
this._ngRedux = ngRedux;
27-
ngRedux.connect(state => state.counter, counter => this.counter = counter, true);
20+
constructor( @Inject('ngRedux') ngRedux) {
21+
this.unsubscribe = ngRedux.connect(this.mapStateToScope, this.mapDispatchToProps)(this);
2822
}
2923

24+
onInit() {}
3025

31-
onInit() {
32-
this.actions = bindActionCreators(CounterActions, this._ngRedux.getStore().dispatch);
26+
onDestroy() {
27+
this.unsubscribe();
3328
}
3429

35-
onDestroy() {
36-
this._ngRedux.disconnect();
30+
mapStateToScope(state) {
31+
return {
32+
counter: state.counter
33+
};
34+
}
35+
36+
mapDispatchToProps(dispatch) {
37+
return { actions: bindActionCreators(CounterActions, dispatch) };
3738
}
3839
}

examples/counter/index.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,13 @@ import {bind} from 'angular2/di';
33
import {createStore, applyMiddleware} from 'redux';
44
import thunk from 'redux-thunk';
55
import {App} from './containers/App';
6-
import {ngRedux} from 'ng2-redux';
6+
import {createRedux} from 'ng2-redux';
77
import {rootReducer} from './reducers';
88

99
const createStoreWithMiddleware = applyMiddleware(thunk)(createStore);
1010
const store = createStoreWithMiddleware(rootReducer);
1111

1212
bootstrap(
1313
App,
14-
[bind('ngRedux').toFactory(() => {
15-
return new ngRedux(store);
16-
})]
17-
);
14+
[createRedux(store)]
15+
);

examples/counter/webpack.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ var path = require('path');
22
var webpack = require('webpack');
33

44
module.exports = {
5-
devtool: 'eval',
5+
devtool: 'source-map',
66
entry: [
77
// Angular 2 Deps
88
'zone.js',

npm-debug.log

Lines changed: 0 additions & 104 deletions
This file was deleted.

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "ng2-redux",
3-
"version": "0.0.1",
3+
"version": "2.0.0-alpha",
44
"description": "Angular 2 bindings for Redux",
55
"main": "./lib/index.js",
66
"scripts": {
@@ -33,6 +33,8 @@
3333
"redux": "^1.0.0 || 1.0.0-alpha || 1.0.0-rc"
3434
},
3535
"dependencies": {
36-
"invariant": "^2.1.0"
36+
"angular2": "^2.0.0-alpha.30",
37+
"invariant": "^2.1.0",
38+
"lodash": "^3.10.1"
3739
}
3840
}

src/connector.js

Lines changed: 62 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,79 @@
11
import shallowEqual from './utils/shallowEqual';
2+
import wrapActionCreators from './utils/wrapActionCreators';
3+
import invariant from 'invariant';
4+
import _ from 'lodash';
25

36
export default class Connector {
47

58
constructor(store) {
6-
this.store = store;
7-
this.unsubscribe = undefined;
9+
this._store = store;
10+
this._defaultMapStateToTarget = () => ({});
11+
this._defaultMapDispatchToTarget = dispatch => ({ dispatch });
812
}
913

10-
disconnect() {
11-
this.unsubscribe();
12-
}
14+
connect = (mapStateToTarget, mapDispatchToTarget) => {
15+
16+
const finalMapStateToTarget = mapStateToTarget || this._defaultMapStateToTarget;
17+
18+
const finalMapDispatchToTarget = _.isPlainObject(mapDispatchToTarget) ?
19+
wrapActionCreators(mapDispatchToTarget) :
20+
mapDispatchToTarget || this._defaultMapDispatchToTarget;
21+
22+
invariant(
23+
_.isFunction(finalMapStateToTarget),
24+
'mapStateToTarget must be a Function. Instead received $s.', finalMapStateToTarget
25+
);
26+
27+
invariant(
28+
_.isPlainObject(finalMapDispatchToTarget) || _.isFunction(finalMapDispatchToTarget),
29+
'mapDispatchToTarget must be a plain Object or a Function. Instead received $s.', finalMapDispatchToTarget
30+
);
31+
32+
let slice = this.getStateSlice(this._store.getState(), finalMapStateToTarget);
33+
34+
const boundActionCreators = finalMapDispatchToTarget(this._store.dispatch);
1335

14-
connect(selectors, callback, disableCaching = false) {
15-
if (!Array.isArray(selectors)) {
16-
selectors = [selectors];
36+
return (target) => {
37+
38+
invariant(
39+
_.isFunction(target) || _.isObject(target),
40+
'The target parameter passed to connect must be a Function or a plain object.'
41+
);
42+
43+
//Initial update
44+
this.updateTarget(target, slice, boundActionCreators);
45+
46+
const unsubscribe = this._store.subscribe(() => {
47+
const nextSlice = this.getStateSlice(this._store.getState(), finalMapStateToTarget);
48+
if (!shallowEqual(slice, nextSlice)) {
49+
slice = nextSlice;
50+
this.updateTarget(target, slice, boundActionCreators);
51+
}
52+
});
53+
return unsubscribe;
1754
}
1855

19-
//Initial update
20-
let params = selectors.map(selector => selector(this.store.getState()));
21-
callback(...params);
56+
}
2257

23-
this.unsubscribe = this.store.subscribe(() => {
24-
let nextParams = selectors.map(selector => selector(this.store.getState()));
25-
if (disableCaching || !shallowEqual(params, nextParams)) {
26-
callback(...nextParams);
27-
params = nextParams;
28-
}
29-
});
3058

31-
return this;
59+
updateTarget(target, StateSlice, dispatch) {
60+
if (_.isFunction(target)) {
61+
target(StateSlice, dispatch);
62+
} else {
63+
_.assign(target, StateSlice, dispatch);
64+
}
3265
}
3366

34-
getStore() {
35-
return this.store;
67+
getStateSlice(state, mapStateToScope) {
68+
const slice = mapStateToScope(state);
69+
70+
invariant(
71+
_.isPlainObject(slice),
72+
'`mapStateToScope` must return an object. Instead received %s.',
73+
slice
74+
);
75+
76+
return slice;
3677
}
3778

3879
}

src/index.js

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,32 @@
1-
export {default as ngRedux} from './connector';
1+
import Connector from './connector';
2+
import {bind, Injector} from 'angular2/di';
3+
let redux = require('redux');
4+
5+
export function createRedux(store) {
6+
const _connector = new Connector(store);
7+
8+
return bind('ngRedux').toFactory(() => {
9+
return { connect: _connector.connect, ...store};
10+
});
11+
}
12+
13+
14+
/*
15+
const createStoreWithMiddleware = applyInjectableMiddleware(thunk, 'promise')(createStore);
16+
*/
17+
/*
18+
export function applyInjectableMiddleware(middlewares) {
19+
const injector = new Injector();
20+
let resolvedMiddlewares = [];
21+
_.forEach(middlewares, middleware => {
22+
_.isString(middleware)
23+
? resolvedMiddlewares.push(Injector.resolve(middleware))
24+
: resolvedMiddlewares.push(middleware)
25+
});
26+
27+
return redux.applyMiddleware(...resolvedMiddlewares);
28+
}
29+
*/
30+
31+
32+

src/utils/wrapActionCreators.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { bindActionCreators } from 'redux';
2+
3+
export default function wrapActionCreators(actionCreators) {
4+
return dispatch => bindActionCreators(actionCreators, dispatch);
5+
}

0 commit comments

Comments
 (0)