This commit is contained in:
crusader 2017-07-25 15:06:59 +09:00
parent 81049e375f
commit bf344fc561
7 changed files with 131 additions and 129 deletions

View File

@ -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;

View File

@ -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<any>;
private sagaMiddleware: SagaMiddleware<any>;
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<void>(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<void> {
const rpcClient = new Promise<void>(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(

View File

@ -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<State>({
signinReducer,
signoutReducer,
signupReducer,
});
export default reducer;

View File

@ -1,5 +0,0 @@
interface State {
}
export default State;

View File

@ -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<any> = createSagaMiddleware();
const middlewares = [sagaMiddleware, routerMiddleware(history)];
const store: Store<State> = createStore<State>(
reducer,
useReduxDevTools ?
compose(
applyMiddleware(...middlewares),
window.devToolsExtension(),
)
:
applyMiddleware(...middlewares),
);
export {
history,
sagaMiddleware,
store,
};

View File

@ -2,55 +2,59 @@ import Action from './Action';
import * as Redux from 'redux';
interface ReducerItem<State> {
initialState: State;
reducer: Redux.Reducer<State>;
}
class ReducerManager {
class ReducerContext {
private static instance: ReducerContext = new ReducerContext();
private reducerMap: Map<string, ReducerItem<any>[]>;
public constructor() {
private constructor() {
this.reducerMap = new Map();
}
public putReducer<State>(type: string, initialState: State, reducer: Redux.Reducer<State>): 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, A extends Action>(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<State>(type: string, reducer: Redux.Reducer<State>): void {
let reducerItems: ReducerItem<any>[];
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<State> = {
initialState: initialState,
reducer: reducer,
};
reducerItems.push(reducerItem);
}
public putReducers<State>(initialState: State, handlers: Redux.ReducersMapObject): void {
for(let type in handlers) {
if (handlers.hasOwnProperty(type)) {
this.putReducer(type, initialState, handlers[type]);
}
}
}
public reducer<State, A extends Action>(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;

View File

@ -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<Member | Error>) => SigninState;
// export type reducer = (state: SigninState, action: Action<Member | Error>) => SigninState;
export const reducer: reducer = createReducer(signinDefaultState, {
[SigninActionTypes.REQUEST_SUCCESS]: (state: SigninState, action: Action<Member>): SigninState => {
// export const reducer: reducer = createReducer(signinDefaultState, {
// [SigninActionTypes.REQUEST_SUCCESS]: (state: SigninState = signinDefaultState, action: Action<Member>): SigninState => {
// return state;
// },
// [SigninActionTypes.REQUEST_FAILURE]: (state: SigninState = signinDefaultState, action: Action<Error>): SigninState => {
// return state;
// },
// });
const reducer: ReducersMapObject = {
[SigninActionTypes.REQUEST_SUCCESS]: (state: SigninState = signinDefaultState, action: Action<Member>): SigninState => {
return state;
},
[SigninActionTypes.REQUEST_FAILURE]: (state: SigninState, action: Action<Error>): SigninState => {
[SigninActionTypes.REQUEST_FAILURE]: (state: SigninState = signinDefaultState, action: Action<Error>): SigninState => {
return state;
},
});
};
export default reducer;
// export const reducer: reducer = (state: SigninState = signinDefaultState, action: Action<Member | Error>): SigninState => {
// switch (action.type) {