Skip to content

Commit 5dbadbc

Browse files
authored
Merge pull request #2 from ebarriosara/'03_Implementation'
Add redux
2 parents 7e1a2f6 + a155c34 commit 5dbadbc

File tree

11 files changed

+444
-167
lines changed

11 files changed

+444
-167
lines changed

03 Add redux/package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
"devDependencies": {
1313
"@types/react": "^16.0.22",
1414
"@types/react-dom": "^16.0.3",
15+
"@types/react-redux": "^5.0.13",
1516
"awesome-typescript-loader": "^3.3.0",
1617
"babel-core": "^6.26.0",
1718
"babel-preset-env": "^1.6.1",
@@ -28,6 +29,9 @@
2829
"dependencies": {
2930
"bootstrap": "^3.3.7",
3031
"react": "^16.1.0",
31-
"react-dom": "^16.1.0"
32+
"react-dom": "^16.1.0",
33+
"react-redux": "^5.0.6",
34+
"redux": "^3.7.2",
35+
"redux-thunk": "^2.2.0"
3236
}
3337
}

03 Add redux/readme.md

Lines changed: 332 additions & 137 deletions
Large diffs are not rendered by default.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { MemberEntity } from '../api/model';
2+
import { actionsDefs } from '../const';
3+
import { fetchMemberList } from '../api';
4+
5+
export const fetchMemberListRequestStart = () => (dispatcher) => {
6+
const promise = fetchMemberList();
7+
8+
promise.then((memberList) => {
9+
dispatcher(fetchMemberListCompleted(memberList));
10+
});
11+
}
12+
13+
const fetchMemberListCompleted = (memberList : MemberEntity[]) => ({
14+
type: actionsDefs.FETCH_MEMBERS_COMPLETED,
15+
payload: memberList,
16+
});

03 Add redux/src/actions/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { fetchMemberListRequestStart } from './fetchMemberList';

03 Add redux/src/const/actionsDefs.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
const prefix = 'MEMBERS_MODULE';
2+
3+
export const actionsDefs = {
4+
FETCH_MEMBERS_COMPLETED: `[${prefix}][1] Member Fetching Completed fetchMembersCompleted`,
5+
}

03 Add redux/src/const/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { actionsDefs } from './actionsDefs';

03 Add redux/src/main.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import * as React from 'react';
22
import * as ReactDOM from 'react-dom';
3-
3+
import { Provider } from 'react-redux';
4+
import { store } from './store';
45
import { MemberListContainer } from './pages/members';
56

67
ReactDOM.render(
7-
<MemberListContainer />,
8+
<Provider store={store}>
9+
<MemberListContainer />
10+
</Provider>,
811
document.getElementById('root')
912
);
Lines changed: 16 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,23 @@
11
import * as React from 'react';
2+
import { connect } from 'react-redux';
3+
import { State } from '../../reducers';
24
import { MemberListPage } from './page';
35
import { MemberEntity } from './viewModel';
4-
import { fetchMemberList } from '../../api';
6+
import * as memberApi from '../../api';
57
import { mapMemberListFromModelToVm } from './mapper';
8+
import { fetchMemberListRequestStart } from '../../actions';
69

7-
interface State {
8-
memberList : MemberEntity[];
9-
}
10+
const mapStateToProps = (state: State) => ({
11+
// This mapping is necessary because we have two different ModelEntity interfaces with the same name.
12+
// This could be improved using selectors.
13+
memberList: mapMemberListFromModelToVm(state.memberListReducer.memberList),
14+
});
1015

11-
export class MemberListContainer extends React.Component<{}, State> {
16+
const mapDispatchToProps = (dispatch) => ({
17+
fetchMemberList: () => { dispatch(fetchMemberListRequestStart()) }
18+
});
1219

13-
constructor(props) {
14-
super(props);
15-
this.state = { memberList: [] };
16-
}
17-
18-
fetchMembers = () => {
19-
fetchMemberList().then((memberList) => {
20-
this.setState({
21-
memberList: mapMemberListFromModelToVm(memberList),
22-
});
23-
});
24-
}
25-
26-
render() {
27-
return (
28-
<MemberListPage
29-
memberList={this.state.memberList}
30-
fetchMemberList={this.fetchMembers}
31-
/>
32-
);
33-
}
34-
}
20+
export const MemberListContainer = connect(
21+
mapStateToProps,
22+
mapDispatchToProps,
23+
)(MemberListPage);

03 Add redux/src/reducers/index.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { combineReducers } from 'redux';
2+
import { memberListReducer, MemberListState } from './memberListReducer';
3+
4+
export interface State {
5+
memberListReducer : MemberListState;
6+
}
7+
8+
export const reducers = combineReducers<State>({
9+
memberListReducer,
10+
});
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { MemberEntity } from '../api/model';
2+
import { actionsDefs } from '../const';
3+
4+
// We create an object showing how spread operator (...) works because it helps keeping the object inmutable,
5+
// but we could have set the state directly to an array of members.
6+
export interface MemberListState {
7+
memberList : MemberEntity[];
8+
}
9+
10+
// The interface BaseAction could be promoted to a common file and be reused in other reducers
11+
interface BaseAction {
12+
type : string;
13+
payload : any;
14+
}
15+
16+
const createDefaultState = () => ({
17+
memberList: [],
18+
});
19+
20+
export const memberListReducer = (state : MemberListState = createDefaultState(), action : BaseAction) : MemberListState => {
21+
switch (action.type) {
22+
case actionsDefs.FETCH_MEMBERS_COMPLETED:
23+
// Return the new state
24+
return handleFetchMembersCompleted(state, action.payload);
25+
}
26+
27+
return state;
28+
}
29+
30+
const handleFetchMembersCompleted = (state : MemberListState, memberList : MemberEntity[]) : MemberListState => ({
31+
// We could have simply returned the list of members, but we are returning an object with the list of members
32+
// using spread operator to show how it helps keeping objects inmutable
33+
...state,
34+
memberList,
35+
});

0 commit comments

Comments
 (0)