From bf344fc561db5aa4c4ffc6a6ac61ce4ba455f147 Mon Sep 17 00:00:00 2001 From: crusader Date: Tue, 25 Jul 2017 15:06:59 +0900 Subject: [PATCH] reducer --- src/ts/@overflow/app/config/index.ts | 22 +++++ src/ts/@overflow/app/index.tsx | 88 +++++++++++++------ src/ts/@overflow/app/redux/reducer/index.ts | 17 ---- src/ts/@overflow/app/redux/state/index.ts | 5 -- src/ts/@overflow/app/redux/store.ts | 47 ---------- .../{ReducerManager.ts => ReducerContext.ts} | 60 +++++++------ .../@overflow/member/redux/reducer/signIn.ts | 21 +++-- 7 files changed, 131 insertions(+), 129 deletions(-) delete mode 100644 src/ts/@overflow/app/redux/reducer/index.ts delete mode 100644 src/ts/@overflow/app/redux/state/index.ts delete mode 100644 src/ts/@overflow/app/redux/store.ts rename src/ts/@overflow/commons/redux/{ReducerManager.ts => ReducerContext.ts} (51%) diff --git a/src/ts/@overflow/app/config/index.ts b/src/ts/@overflow/app/config/index.ts index 24ced6b..1a72e80 100644 --- a/src/ts/@overflow/app/config/index.ts +++ b/src/ts/@overflow/app/config/index.ts @@ -1,3 +1,6 @@ +import { ReducersMapObject } from 'redux'; +import signInReducer from '@overflow/member/redux/reducer/signIn'; + // Container Configuration export interface ContainerConfig { placeholderID: string; @@ -14,16 +17,35 @@ const rpcConfig: RPCConfig = { url: 'ws://127.0.0.1:18081/rpc', }; +// Redux Configuration +export interface ReduxConfig { + state: ReduxState; + reducerMaps: ReducersMapObject[]; +} +export interface ReduxState { + +} +const reduxState: ReduxState = {}; + +const reduxConfig: ReduxConfig = { + state: reduxState, + reducerMaps: [ + signInReducer, + ], +}; + // Configuration export interface Config { container: ContainerConfig; rpc: RPCConfig; + redux: ReduxConfig; } const config: Config = { container: containerConfig, rpc: rpcConfig, + redux: reduxConfig, }; export default config; diff --git a/src/ts/@overflow/app/index.tsx b/src/ts/@overflow/app/index.tsx index 61b1445..94b9c70 100644 --- a/src/ts/@overflow/app/index.tsx +++ b/src/ts/@overflow/app/index.tsx @@ -1,10 +1,36 @@ import * as React from 'react'; import * as ReactDOM from 'react-dom'; -import { Provider, Store } from 'react-redux'; -import { ConnectedRouter } from 'react-router-redux'; -import createSagaMiddleware, { SagaMiddleware } from 'redux-saga'; -import { History } from 'history'; -import { AppContainer } from 'react-hot-loader'; +import { + applyMiddleware, + compose, + createStore, + GenericStoreEnhancer, + Middleware, + Store, +} from 'redux'; + +import { + Provider, +} from 'react-redux'; + +import { + ConnectedRouter, + routerMiddleware, +} from 'react-router-redux'; + +import createSagaMiddleware, { + SagaMiddleware, +} from 'redux-saga'; + +import { + createHashHistory, + History, +} from 'history'; + +import { + AppContainer, +} from 'react-hot-loader'; + import * as injectTapEventPlugin from 'react-tap-event-plugin'; @@ -12,12 +38,9 @@ import Platform from '@overflow/commons/platform'; import AppContext from '@overflow/commons/context'; import * as AppContextLifecycleActions from '@overflow/commons/context/redux/action/lifecycle'; import WebSocketRPC from '@overflow/commons/websocket/WebSocketRPC'; -import ReducerManager from '@overflow/commons/redux/ReducerManager'; +import ReducerContext from '@overflow/commons/redux/ReducerContext'; - -import { store, sagaMiddleware, history } from './redux/store'; - -import appConfig, { Config } from './config'; +import appConfig, { Config, ReduxState } from './config'; import sagas from './redux/saga'; // import routes from './router'; @@ -26,9 +49,13 @@ import App from './views/App'; injectTapEventPlugin(); -const isProduction:boolean = process.env.NODE_ENV === 'production' ? true : false; +// const isProduction:boolean = process.env.NODE_ENV === 'production' ? true : false; +// const useReduxDevTools = window.devToolsExtension && !isProduction ? true : false; class Application { + private static isProduction:boolean = process.env.NODE_ENV === 'production' ? true : false; + private static useReduxDevTools:boolean = window.devToolsExtension && !Application.isProduction ? true : false; + private config: Config; private container: HTMLElement; private context: AppContext; @@ -36,14 +63,11 @@ class Application { private store: Store; private sagaMiddleware: SagaMiddleware; private history: History; - private reducerManager: ReducerManager; + public constructor() { this.config = appConfig; - this.sagaMiddleware = sagaMiddleware; - this.store = store; - this.history = history; - this.reducerManager = new ReducerManager(); + this.history = createHashHistory(); } public static Run(): void { @@ -58,7 +82,8 @@ class Application { this.context = await this.initContext(); // this.rpcClient = await this.initRpcClient(); - await this.initSagaEffect(); + + await this.initRedux(); this.store.dispatch(AppContextLifecycleActions.initialized()); @@ -97,21 +122,30 @@ class Application { const init = new Promise(resolve => { // state tree // reducer + for (let reducerMap of this.config.redux.reducerMaps) { + ReducerContext.putReducers(reducerMap); + } // middleware + let middlewares: Middleware[] = new Array(); + this.sagaMiddleware = createSagaMiddleware(); + middlewares.push(this.sagaMiddleware); + + let routerReduxMiddleware = routerMiddleware(this.history); + middlewares.push(routerReduxMiddleware); + + // store + let middleware: GenericStoreEnhancer = applyMiddleware(...middlewares); + this.store = createStore( + ReducerContext.reducer, + this.config.redux.state, + Application.useReduxDevTools ? compose(middleware, window.devToolsExtension()) : middleware, + ); // saga - - }); - - return init; - } - - private initSagaEffect(): Promise { - const rpcClient = new Promise(resolve => { this.sagaMiddleware.run(sagas); resolve(); }); - return rpcClient; + return init; } private displayLoading(): void { @@ -148,7 +182,7 @@ class Application { private displayApp(): void { - isProduction ? this.displayProductionApp() : this.displayDebugApp(); + Application.isProduction ? this.displayProductionApp() : this.displayDebugApp(); } private displayProductionApp(): void { ReactDOM.render( diff --git a/src/ts/@overflow/app/redux/reducer/index.ts b/src/ts/@overflow/app/redux/reducer/index.ts deleted file mode 100644 index dba0d32..0000000 --- a/src/ts/@overflow/app/redux/reducer/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Action, combineReducers } from 'redux'; -import State from '../state'; - -import { reducer as signinReducer} from '@overflow/member/redux/reducer/signIn'; -import { reducer as signoutReducer} from '@overflow/member/redux/reducer/signOut'; -import { reducer as signupReducer} from '@overflow/member/redux/reducer/signUp'; - -import { ConnectedRouter } from 'react-router-redux'; - - -const reducer = combineReducers({ - signinReducer, - signoutReducer, - signupReducer, -}); - -export default reducer; diff --git a/src/ts/@overflow/app/redux/state/index.ts b/src/ts/@overflow/app/redux/state/index.ts deleted file mode 100644 index 9943f9d..0000000 --- a/src/ts/@overflow/app/redux/state/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -interface State { - -} - -export default State; diff --git a/src/ts/@overflow/app/redux/store.ts b/src/ts/@overflow/app/redux/store.ts deleted file mode 100644 index 211c88f..0000000 --- a/src/ts/@overflow/app/redux/store.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { - applyMiddleware, - compose, - createStore, - Store, -} from 'redux'; -import { routerMiddleware } from 'react-router-redux'; -import createSagaMiddleware, { - SagaMiddleware, -} from 'redux-saga'; - -import { - createHashHistory, - History, -} from 'history'; - -import { - EnhancerOptions, - composeWithDevTools, -} from 'redux-devtools-extension/logOnlyInProduction'; - -import reducer from './reducer'; -import State from './state'; - -const useReduxDevTools = window.devToolsExtension && process.env.NODE_ENV !== 'production' ? true : false; - - -const history = createHashHistory(); -const sagaMiddleware: SagaMiddleware = createSagaMiddleware(); -const middlewares = [sagaMiddleware, routerMiddleware(history)]; - -const store: Store = createStore( - reducer, - useReduxDevTools ? - compose( - applyMiddleware(...middlewares), - window.devToolsExtension(), - ) - : - applyMiddleware(...middlewares), -); - -export { - history, - sagaMiddleware, - store, -}; diff --git a/src/ts/@overflow/commons/redux/ReducerManager.ts b/src/ts/@overflow/commons/redux/ReducerContext.ts similarity index 51% rename from src/ts/@overflow/commons/redux/ReducerManager.ts rename to src/ts/@overflow/commons/redux/ReducerContext.ts index d136ecc..f327577 100644 --- a/src/ts/@overflow/commons/redux/ReducerManager.ts +++ b/src/ts/@overflow/commons/redux/ReducerContext.ts @@ -2,55 +2,59 @@ import Action from './Action'; import * as Redux from 'redux'; interface ReducerItem { - initialState: State; reducer: Redux.Reducer; } -class ReducerManager { +class ReducerContext { + private static instance: ReducerContext = new ReducerContext(); private reducerMap: Map[]>; - public constructor() { + private constructor() { this.reducerMap = new Map(); } - public putReducer(type: string, initialState: State, reducer: Redux.Reducer): void { + public static getInstance(): ReducerContext { + return ReducerContext.instance; + } + + public static putReducers(handlers: Redux.ReducersMapObject): void { + for(let type in handlers) { + if (handlers.hasOwnProperty(type)) { + ReducerContext.getInstance().putReducer(type, handlers[type]); + } + } + } + + public static reducer(state: State, action: A): State { + const actionType = action.type; + if (ReducerContext.getInstance().reducerMap.has(actionType)) { + let reducerItems = ReducerContext.getInstance().reducerMap.get(actionType); + for (let reducerItem of reducerItems) { + let reducer = reducerItem.reducer; + state = reducer(state, action); + } + } else { + console.log(`Reducer for [${actionType}] is not exist in the context.`); + } + return state; + } + + private putReducer(type: string, reducer: Redux.Reducer): void { let reducerItems: ReducerItem[]; if (!this.reducerMap.has(type)) { reducerItems = new Array(); this.reducerMap.set(type, reducerItems); } else { reducerItems = this.reducerMap.get(type); + console.log(`Count of reducer[${type}] is ${reducerItems.length + 1}`); } let reducerItem: ReducerItem = { - initialState: initialState, reducer: reducer, }; reducerItems.push(reducerItem); } - public putReducers(initialState: State, handlers: Redux.ReducersMapObject): void { - for(let type in handlers) { - if (handlers.hasOwnProperty(type)) { - this.putReducer(type, initialState, handlers[type]); - } - } - } - - public reducer(state: State, action: A): State { - const actionType = action.type; - if (this.reducerMap.has(actionType)) { - let reducerItems = this.reducerMap.get(actionType); - for (let reducerItem of reducerItems) { - let initialState = reducerItem.initialState; - let reducer = reducerItem.reducer; - state = reducer(state, action); - } - } else { - console.log(`Reducer for [${actionType}] is not loaded.`); - } - return state; - } } -export default ReducerManager; +export default ReducerContext; diff --git a/src/ts/@overflow/member/redux/reducer/signIn.ts b/src/ts/@overflow/member/redux/reducer/signIn.ts index d06efb4..078b8b1 100644 --- a/src/ts/@overflow/member/redux/reducer/signIn.ts +++ b/src/ts/@overflow/member/redux/reducer/signIn.ts @@ -1,21 +1,32 @@ import Action from '@overflow/commons/redux/Action'; +import { ReducersMapObject } from 'redux'; import createReducer from '@overflow/commons/redux/createReducer'; import Member from '@overflow/member/api/model/Member'; import * as SigninActionTypes from '../action/signIn'; import SigninState, { defaultState as signinDefaultState } from '../state/SignIn'; -export type reducer = (state: SigninState, action: Action) => SigninState; +// export type reducer = (state: SigninState, action: Action) => SigninState; -export const reducer: reducer = createReducer(signinDefaultState, { - [SigninActionTypes.REQUEST_SUCCESS]: (state: SigninState, action: Action): SigninState => { +// export const reducer: reducer = createReducer(signinDefaultState, { + // [SigninActionTypes.REQUEST_SUCCESS]: (state: SigninState = signinDefaultState, action: Action): SigninState => { + // return state; + // }, + // [SigninActionTypes.REQUEST_FAILURE]: (state: SigninState = signinDefaultState, action: Action): SigninState => { + // return state; + // }, +// }); + +const reducer: ReducersMapObject = { + [SigninActionTypes.REQUEST_SUCCESS]: (state: SigninState = signinDefaultState, action: Action): SigninState => { return state; }, - [SigninActionTypes.REQUEST_FAILURE]: (state: SigninState, action: Action): SigninState => { + [SigninActionTypes.REQUEST_FAILURE]: (state: SigninState = signinDefaultState, action: Action): SigninState => { return state; }, -}); +}; +export default reducer; // export const reducer: reducer = (state: SigninState = signinDefaultState, action: Action): SigninState => { // switch (action.type) {