reducer
This commit is contained in:
parent
81049e375f
commit
bf344fc561
|
@ -1,3 +1,6 @@
|
||||||
|
import { ReducersMapObject } from 'redux';
|
||||||
|
import signInReducer from '@overflow/member/redux/reducer/signIn';
|
||||||
|
|
||||||
// Container Configuration
|
// Container Configuration
|
||||||
export interface ContainerConfig {
|
export interface ContainerConfig {
|
||||||
placeholderID: string;
|
placeholderID: string;
|
||||||
|
@ -14,16 +17,35 @@ const rpcConfig: RPCConfig = {
|
||||||
url: 'ws://127.0.0.1:18081/rpc',
|
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
|
// Configuration
|
||||||
export interface Config {
|
export interface Config {
|
||||||
container: ContainerConfig;
|
container: ContainerConfig;
|
||||||
rpc: RPCConfig;
|
rpc: RPCConfig;
|
||||||
|
redux: ReduxConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
const config: Config = {
|
const config: Config = {
|
||||||
container: containerConfig,
|
container: containerConfig,
|
||||||
rpc: rpcConfig,
|
rpc: rpcConfig,
|
||||||
|
redux: reduxConfig,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default config;
|
export default config;
|
||||||
|
|
|
@ -1,10 +1,36 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import * as ReactDOM from 'react-dom';
|
import * as ReactDOM from 'react-dom';
|
||||||
import { Provider, Store } from 'react-redux';
|
import {
|
||||||
import { ConnectedRouter } from 'react-router-redux';
|
applyMiddleware,
|
||||||
import createSagaMiddleware, { SagaMiddleware } from 'redux-saga';
|
compose,
|
||||||
import { History } from 'history';
|
createStore,
|
||||||
import { AppContainer } from 'react-hot-loader';
|
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';
|
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 AppContext from '@overflow/commons/context';
|
||||||
import * as AppContextLifecycleActions from '@overflow/commons/context/redux/action/lifecycle';
|
import * as AppContextLifecycleActions from '@overflow/commons/context/redux/action/lifecycle';
|
||||||
import WebSocketRPC from '@overflow/commons/websocket/WebSocketRPC';
|
import WebSocketRPC from '@overflow/commons/websocket/WebSocketRPC';
|
||||||
import ReducerManager from '@overflow/commons/redux/ReducerManager';
|
import ReducerContext from '@overflow/commons/redux/ReducerContext';
|
||||||
|
|
||||||
|
import appConfig, { Config, ReduxState } from './config';
|
||||||
import { store, sagaMiddleware, history } from './redux/store';
|
|
||||||
|
|
||||||
import appConfig, { Config } from './config';
|
|
||||||
|
|
||||||
import sagas from './redux/saga';
|
import sagas from './redux/saga';
|
||||||
// import routes from './router';
|
// import routes from './router';
|
||||||
|
@ -26,9 +49,13 @@ import App from './views/App';
|
||||||
|
|
||||||
injectTapEventPlugin();
|
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 {
|
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 config: Config;
|
||||||
private container: HTMLElement;
|
private container: HTMLElement;
|
||||||
private context: AppContext;
|
private context: AppContext;
|
||||||
|
@ -36,14 +63,11 @@ class Application {
|
||||||
private store: Store<any>;
|
private store: Store<any>;
|
||||||
private sagaMiddleware: SagaMiddleware<any>;
|
private sagaMiddleware: SagaMiddleware<any>;
|
||||||
private history: History;
|
private history: History;
|
||||||
private reducerManager: ReducerManager;
|
|
||||||
|
|
||||||
public constructor() {
|
public constructor() {
|
||||||
this.config = appConfig;
|
this.config = appConfig;
|
||||||
this.sagaMiddleware = sagaMiddleware;
|
this.history = createHashHistory();
|
||||||
this.store = store;
|
|
||||||
this.history = history;
|
|
||||||
this.reducerManager = new ReducerManager();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Run(): void {
|
public static Run(): void {
|
||||||
|
@ -58,7 +82,8 @@ class Application {
|
||||||
|
|
||||||
this.context = await this.initContext();
|
this.context = await this.initContext();
|
||||||
// this.rpcClient = await this.initRpcClient();
|
// this.rpcClient = await this.initRpcClient();
|
||||||
await this.initSagaEffect();
|
|
||||||
|
await this.initRedux();
|
||||||
|
|
||||||
this.store.dispatch(AppContextLifecycleActions.initialized());
|
this.store.dispatch(AppContextLifecycleActions.initialized());
|
||||||
|
|
||||||
|
@ -97,21 +122,30 @@ class Application {
|
||||||
const init = new Promise<void>(resolve => {
|
const init = new Promise<void>(resolve => {
|
||||||
// state tree
|
// state tree
|
||||||
// reducer
|
// reducer
|
||||||
// middleware
|
for (let reducerMap of this.config.redux.reducerMaps) {
|
||||||
// saga
|
ReducerContext.putReducers(reducerMap);
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
return init;
|
|
||||||
}
|
}
|
||||||
|
// middleware
|
||||||
|
let middlewares: Middleware[] = new Array();
|
||||||
|
this.sagaMiddleware = createSagaMiddleware();
|
||||||
|
middlewares.push(this.sagaMiddleware);
|
||||||
|
|
||||||
private initSagaEffect(): Promise<void> {
|
let routerReduxMiddleware = routerMiddleware(this.history);
|
||||||
const rpcClient = new Promise<void>(resolve => {
|
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
|
||||||
this.sagaMiddleware.run(sagas);
|
this.sagaMiddleware.run(sagas);
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
|
|
||||||
return rpcClient;
|
return init;
|
||||||
}
|
}
|
||||||
|
|
||||||
private displayLoading(): void {
|
private displayLoading(): void {
|
||||||
|
@ -148,7 +182,7 @@ class Application {
|
||||||
|
|
||||||
|
|
||||||
private displayApp(): void {
|
private displayApp(): void {
|
||||||
isProduction ? this.displayProductionApp() : this.displayDebugApp();
|
Application.isProduction ? this.displayProductionApp() : this.displayDebugApp();
|
||||||
}
|
}
|
||||||
private displayProductionApp(): void {
|
private displayProductionApp(): void {
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
|
|
|
@ -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;
|
|
|
@ -1,5 +0,0 @@
|
||||||
interface State {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export default State;
|
|
|
@ -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,
|
|
||||||
};
|
|
|
@ -2,55 +2,59 @@ import Action from './Action';
|
||||||
import * as Redux from 'redux';
|
import * as Redux from 'redux';
|
||||||
|
|
||||||
interface ReducerItem<State> {
|
interface ReducerItem<State> {
|
||||||
initialState: State;
|
|
||||||
reducer: Redux.Reducer<State>;
|
reducer: Redux.Reducer<State>;
|
||||||
}
|
}
|
||||||
|
|
||||||
class ReducerManager {
|
class ReducerContext {
|
||||||
|
private static instance: ReducerContext = new ReducerContext();
|
||||||
private reducerMap: Map<string, ReducerItem<any>[]>;
|
private reducerMap: Map<string, ReducerItem<any>[]>;
|
||||||
|
|
||||||
public constructor() {
|
private constructor() {
|
||||||
this.reducerMap = new Map();
|
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>[];
|
let reducerItems: ReducerItem<any>[];
|
||||||
if (!this.reducerMap.has(type)) {
|
if (!this.reducerMap.has(type)) {
|
||||||
reducerItems = new Array();
|
reducerItems = new Array();
|
||||||
this.reducerMap.set(type, reducerItems);
|
this.reducerMap.set(type, reducerItems);
|
||||||
} else {
|
} else {
|
||||||
reducerItems = this.reducerMap.get(type);
|
reducerItems = this.reducerMap.get(type);
|
||||||
|
console.log(`Count of reducer[${type}] is ${reducerItems.length + 1}`);
|
||||||
}
|
}
|
||||||
let reducerItem: ReducerItem<State> = {
|
let reducerItem: ReducerItem<State> = {
|
||||||
initialState: initialState,
|
|
||||||
reducer: reducer,
|
reducer: reducer,
|
||||||
};
|
};
|
||||||
|
|
||||||
reducerItems.push(reducerItem);
|
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 {
|
export default ReducerContext;
|
||||||
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;
|
|
|
@ -1,21 +1,32 @@
|
||||||
import Action from '@overflow/commons/redux/Action';
|
import Action from '@overflow/commons/redux/Action';
|
||||||
|
import { ReducersMapObject } from 'redux';
|
||||||
import createReducer from '@overflow/commons/redux/createReducer';
|
import createReducer from '@overflow/commons/redux/createReducer';
|
||||||
import Member from '@overflow/member/api/model/Member';
|
import Member from '@overflow/member/api/model/Member';
|
||||||
|
|
||||||
import * as SigninActionTypes from '../action/signIn';
|
import * as SigninActionTypes from '../action/signIn';
|
||||||
import SigninState, { defaultState as signinDefaultState } from '../state/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, {
|
// export const reducer: reducer = createReducer(signinDefaultState, {
|
||||||
[SigninActionTypes.REQUEST_SUCCESS]: (state: SigninState, action: Action<Member>): SigninState => {
|
// [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;
|
return state;
|
||||||
},
|
},
|
||||||
[SigninActionTypes.REQUEST_FAILURE]: (state: SigninState, action: Action<Error>): SigninState => {
|
[SigninActionTypes.REQUEST_FAILURE]: (state: SigninState = signinDefaultState, action: Action<Error>): SigninState => {
|
||||||
return state;
|
return state;
|
||||||
},
|
},
|
||||||
});
|
};
|
||||||
|
|
||||||
|
export default reducer;
|
||||||
|
|
||||||
// export const reducer: reducer = (state: SigninState = signinDefaultState, action: Action<Member | Error>): SigninState => {
|
// export const reducer: reducer = (state: SigninState = signinDefaultState, action: Action<Member | Error>): SigninState => {
|
||||||
// switch (action.type) {
|
// switch (action.type) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user