File tree Expand file tree Collapse file tree 11 files changed +444
-167
lines changed Expand file tree Collapse file tree 11 files changed +444
-167
lines changed Original file line number Diff line number Diff line change 12
12
"devDependencies" : {
13
13
"@types/react" : " ^16.0.22" ,
14
14
"@types/react-dom" : " ^16.0.3" ,
15
+ "@types/react-redux" : " ^5.0.13" ,
15
16
"awesome-typescript-loader" : " ^3.3.0" ,
16
17
"babel-core" : " ^6.26.0" ,
17
18
"babel-preset-env" : " ^1.6.1" ,
28
29
"dependencies" : {
29
30
"bootstrap" : " ^3.3.7" ,
30
31
"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"
32
36
}
33
37
}
Load Diff Large diffs are not rendered by default.
Original file line number Diff line number Diff line change
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
+ } ) ;
Original file line number Diff line number Diff line change
1
+ export { fetchMemberListRequestStart } from './fetchMemberList' ;
Original file line number Diff line number Diff line change
1
+ const prefix = 'MEMBERS_MODULE' ;
2
+
3
+ export const actionsDefs = {
4
+ FETCH_MEMBERS_COMPLETED : `[${ prefix } ][1] Member Fetching Completed fetchMembersCompleted` ,
5
+ }
Original file line number Diff line number Diff line change
1
+ export { actionsDefs } from './actionsDefs' ;
Original file line number Diff line number Diff line change 1
1
import * as React from 'react' ;
2
2
import * as ReactDOM from 'react-dom' ;
3
-
3
+ import { Provider } from 'react-redux' ;
4
+ import { store } from './store' ;
4
5
import { MemberListContainer } from './pages/members' ;
5
6
6
7
ReactDOM . render (
7
- < MemberListContainer /> ,
8
+ < Provider store = { store } >
9
+ < MemberListContainer />
10
+ </ Provider > ,
8
11
document . getElementById ( 'root' )
9
12
) ;
Original file line number Diff line number Diff line change 1
1
import * as React from 'react' ;
2
+ import { connect } from 'react-redux' ;
3
+ import { State } from '../../reducers' ;
2
4
import { MemberListPage } from './page' ;
3
5
import { MemberEntity } from './viewModel' ;
4
- import { fetchMemberList } from '../../api' ;
6
+ import * as memberApi from '../../api' ;
5
7
import { mapMemberListFromModelToVm } from './mapper' ;
8
+ import { fetchMemberListRequestStart } from '../../actions' ;
6
9
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
+ } ) ;
10
15
11
- export class MemberListContainer extends React . Component < { } , State > {
16
+ const mapDispatchToProps = ( dispatch ) => ( {
17
+ fetchMemberList : ( ) => { dispatch ( fetchMemberListRequestStart ( ) ) }
18
+ } ) ;
12
19
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 ) ;
Original file line number Diff line number Diff line change
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
+ } ) ;
Original file line number Diff line number Diff line change
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
+ } ) ;
You can’t perform that action at this time.
0 commit comments