Skip to content

Commit cce252b

Browse files
Converts counter to redux-actions
1 parent 683cc5b commit cce252b

15 files changed

+84
-53
lines changed

package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
"gulp-util": "^3.0.7",
3636
"jsdom": "^8.2.0",
3737
"jsx-chai": "^2.0.0",
38+
"mime": "^1.3.4",
3839
"mkdirp": "^0.5.1",
3940
"mocha": "^2.4.5",
4041
"mocha-clean": "^1.0.0",
@@ -67,6 +68,7 @@
6768
"immutable": "^3.7.6",
6869
"isomorphic-fetch": "^2.2.1",
6970
"lodash": "^4.6.1",
71+
"normalizr": "^2.0.1",
7072
"object.assign": "^4.0.3",
7173
"radium": "^0.17.1",
7274
"react": "^0.14.8",
@@ -76,6 +78,8 @@
7678
"react-router": "^2.0.1",
7779
"react-router-redux": "^4.0.1",
7880
"redux": "^3.3.1",
79-
"redux-thunk": "^2.0.1"
81+
"redux-actions": "^0.9.1",
82+
"redux-thunk": "^2.0.1",
83+
"reselect": "^2.5.1"
8084
}
8185
}
Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,22 @@
11
import { expect } from 'chai';
22
import * as React from 'react';
3-
import * as TestUtils from 'react-addons-test-utils';
3+
import { createRenderer } from 'react-addons-test-utils';
44
import BannerComponent, { BannerKind } from './BannerComponent';
55

66
describe('BannerComponent', function() {
7+
let renderer;
8+
9+
beforeEach(() => {
10+
renderer = createRenderer();
11+
});
12+
713
it('works', function() {
8-
const instance = TestUtils.renderIntoDocument(
14+
renderer.render(
915
<BannerComponent kind={BannerKind.primary} />
1016
);
1117

18+
const instance = renderer.getRenderOutput();
19+
1220
expect(instance).to.be.ok;
1321
});
1422
});

src/components/CounterComponent-spec.tsx

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,37 +4,38 @@ import * as React from 'react';
44
import * as TestUtils from 'react-addons-test-utils';
55
import CounterComponent, { CounterProps } from './CounterComponent';
66

7-
describe('CounterComponent', function() {
7+
describe('CounterComponent', () => {
88
let props: CounterProps;
99
let instance;
1010

11-
beforeEach(function() {
11+
beforeEach(() => {
1212
props = {
1313
counter: { value: 0 },
14-
increaseCounter: sinon.spy()
14+
increaseCounter: sinon.spy(),
15+
decreaseCounter: sinon.spy(),
1516
};
1617

1718
instance = TestUtils.renderIntoDocument(<CounterComponent {...props} />);
1819
});
1920

20-
describe('interaction', function() {
21-
it('triggers the action when increase button is clicked', function() {
21+
describe('interaction', () => {
22+
it('triggers the action when increase button is clicked', () => {
2223
TestUtils.Simulate.click(instance.refs.increase);
2324
expect(props.increaseCounter).to.have.been.calledWith(+1);
2425
});
2526

26-
it('triggers the action when decrease button is clicked', function() {
27+
it('triggers the action when decrease button is clicked', () => {
2728
TestUtils.Simulate.click(instance.refs.decrease);
28-
expect(props.increaseCounter).to.have.been.calledWith(-1);
29+
expect(props.decreaseCounter).to.have.been.calledWith(1);
2930
});
3031
});
3132

32-
describe('display', function() {
33-
it('renders initial value', function() {
33+
describe('display', () => {
34+
it('renders initial value', () => {
3435
expect(instance.refs.displayValue.innerHTML).to.equal(props.counter.value.toString());
3536
});
3637

37-
it('renders new value', function() {
38+
it('renders new value', () => {
3839
props.counter.value = 100;
3940
instance.forceUpdate();
4041
expect(instance.refs.displayValue.innerHTML).to.equal('100');

src/components/CounterComponent.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
11
import * as React from 'react';
2-
import { ICounterState, ICounterAction } from '../store/counter';
2+
import { ICounterState } from '../store/counter';
33

44
export interface CounterProps {
5-
increaseCounter(amount: number): ICounterAction;
5+
increaseCounter(amount: number);
6+
decreaseCounter(amount: number);
67
counter: ICounterState;
78
}
89

910
export default class CounterComponent extends React.Component<CounterProps, any> {
1011
render() {
11-
const { increaseCounter } = this.props;
12+
const { increaseCounter, decreaseCounter } = this.props;
1213

1314
return (
1415
<div>
1516
value????: <span ref="displayValue">{this.props.counter.value}</span>
1617
<button ref="increase" onClick={() => increaseCounter(+1) }>increase</button>
17-
<button ref="decrease" onClick={() => increaseCounter(-1) }>decrease</button>
18+
<button ref="decrease" onClick={() => decreaseCounter(1) }>decrease</button>
1819
</div>
1920
);
2021
}

src/routes/root/components/ApplicationComponent.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as React from 'react';
22
import { Link } from 'react-router';
33
import { bindActionCreators } from 'redux';
4-
import * as counterActions from '../../../store/counter/actions';
4+
import { increaseCounter, decreaseCounter } from '../../../store/counter';
55
import Counter from '../../../components/CounterComponent';
66

77
declare const DEVELOPMENT;
@@ -11,7 +11,7 @@ const DevTools = DEVELOPMENT && require('../containers/DevToolsContainer').defau
1111
export default class ApplicationContainer extends React.Component<any, any> {
1212
render() {
1313
const { counter, dispatch } = this.props;
14-
const boundCounterActions = bindActionCreators(counterActions, dispatch);
14+
const boundCounterActions = bindActionCreators({ increaseCounter, decreaseCounter }, dispatch);
1515

1616
return (
1717
<div>

src/store/counter/actions-spec.ts

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
11
import { expect } from 'chai';
2-
import { INCREASE_COUNTER, ICounterAction, increaseCounter } from './';
2+
import { INCREASE_COUNTER, DECREASE_COUNTER, increaseCounter, decreaseCounter } from './';
33

4-
describe('counter-actions', function() {
5-
it('creates an action to increase the counter', function() {
6-
const expectedAction: ICounterAction = { type: INCREASE_COUNTER, amount: +1 };
7-
expect(increaseCounter(+1)).to.eql(expectedAction);
8-
});
4+
describe('counter-actions', () => {
5+
it('increaseCounter', () =>
6+
expect(increaseCounter(1)).to.eql({
7+
type: INCREASE_COUNTER,
8+
payload: { value: 1 }
9+
})
10+
);
11+
12+
it('decreaseCounter', () =>
13+
expect(decreaseCounter(1)).to.eql({
14+
type: DECREASE_COUNTER,
15+
payload: { value: 1 }
16+
})
17+
);
918
});

src/store/counter/actions.ts

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
1-
import { INCREASE_COUNTER } from './constants';
2-
import { IAction } from '../interfaces';
1+
import { INCREASE_COUNTER, DECREASE_COUNTER } from './constants';
2+
import { ICounterState } from './state';
3+
import { createAction } from 'redux-actions';
34

4-
export interface ICounterAction extends IAction {
5-
amount: number;
6-
};
7-
8-
export function increaseCounter(amount: number): ICounterAction {
9-
return { type: INCREASE_COUNTER, amount };
10-
};
5+
export const increaseCounter = createAction<number, ICounterState>(INCREASE_COUNTER, value => ({ value }));
6+
export const decreaseCounter = createAction<number, ICounterState>(DECREASE_COUNTER, value => ({ value }));

src/store/counter/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export const INCREASE_COUNTER: string = 'INCREASE_COUNTER';
2+
export const DECREASE_COUNTER: string = 'DECREASE_COUNTER';

src/store/counter/reducer-spec.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import { expect } from 'chai';
2-
import { ICounterAction, INCREASE_COUNTER, counterReducer } from './';
2+
import { counterReducer, increaseCounter, decreaseCounter } from './';
33

4-
const action = (amount: number = 0): ICounterAction => ({ type: INCREASE_COUNTER, amount });
5-
6-
describe('counter-reducer', function() {
7-
it('returns the initial state', () => expect(counterReducer(undefined, action())).to.eql({ value: 0 }));
8-
it('handles INCREASE_COUNTER', () => expect(counterReducer({ value: 10 }, action(1))).to.eql({ value: 11 }));
4+
describe.only('counter-reducer', () => {
5+
it('sets the initial state', () => expect(counterReducer(undefined, increaseCounter(1))).to.eql({ value: 1 }));
6+
it('handles INCREASE_COUNTER', () => expect(counterReducer({ value: 10 }, increaseCounter(1))).to.eql({ value: 11 }));
7+
it('handles DECREASE_COUNTER', () => expect(counterReducer({ value: 10 }, decreaseCounter(1))).to.eql({ value: 9 }));
98
});

src/store/counter/reducer.ts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
1-
import { INCREASE_COUNTER, ICounterState, ICounterAction } from './';
1+
import { INCREASE_COUNTER, DECREASE_COUNTER, ICounterState } from './';
2+
import { handleActions } from 'redux-actions';
23

3-
const initialState: ICounterState = { value: 0 };
4+
const initialState: ICounterState = {
5+
value: 0
6+
};
47

5-
export function counterReducer(state: ICounterState = initialState, action: ICounterAction): ICounterState {
6-
switch (action.type) {
7-
case INCREASE_COUNTER:
8-
return Object.assign({}, state, { value: state.value + action.amount });
9-
default:
10-
return state;
11-
}
12-
}
8+
export const counterReducer = handleActions<ICounterState>({
9+
[INCREASE_COUNTER]: (state, action) => ({
10+
value: state.value + action.payload.value
11+
}),
12+
13+
[DECREASE_COUNTER]: (state, action) => ({
14+
value: state.value - action.payload.value
15+
}),
16+
}, initialState);

src/store/counter/state.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
export type ICounterState = {
22
value: number;
3-
};
3+
}

src/store/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,11 @@ if (DEVELOPMENT) {
1616
}
1717

1818
const reducer = combineReducers({
19+
// entities: combineReducers({
20+
// posts: postsEntitiesReducer,
21+
// }),
1922
counter: counterReducer,
20-
colors: postsReducer,
23+
posts: postsReducer,
2124
routing: routerReducer
2225
});
2326
const initialState = {};

tsd.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@
6464
},
6565
"isomorphic-fetch/isomorphic-fetch.d.ts": {
6666
"commit": "d969b903d1fce89a5e43828ec68458b4f852db4d"
67+
},
68+
"redux-actions/redux-actions.d.ts": {
69+
"commit": "544a35a10866b32afda9c7f029c0764558563f4f"
6770
}
6871
}
6972
}

webpack/config-vendor.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ config.entry.vendor = [
2323
'react-router',
2424
'react-router-redux',
2525
'redux',
26+
'redux-actions',
2627
'redux-thunk',
28+
'reselect',
2729
'whatwg-fetch',
2830
'lodash',
2931
];

webpack/source-map-fix.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,4 @@ module.exports = function (input, inputMap) {
1818
}
1919

2020
callback(err, input, inputMap);
21-
}
21+
};

0 commit comments

Comments
 (0)