モジュール単位での開発をしたい!
悩み
→ 関心空間の単位でディレクトリ分離したい!
⇒
rails-style
re-ducks
悩み
他の表示モードでしか使わないものは読み込みたくない
けど、store とか reducer / middleware って
lazy loading できるんだっけ?
import { IModule } from 'redux-dynamic-modules';
// dependencies
// application imports
import { Actions, Operations } from './operations';
import { Selectors } from './selectors';
import Reducer, { IState } from './reducers';
// ============================================================================
// Type definitions
//
export interface IModuleOwnState
{
app: IState;
}
// ============================================================================
// Dynamic Module
//
function getModule(): IModule<IModuleOwnState> {
return {
id: "ApplicationModule",
reducerMap: {
app: Reducer,
} as any,
// Actions to fire when this module is added/removed
initialActions: [Actions.initialize(null)],
// finalActions: []
// middlewares: [],
};
}
// ============================================================================
// Exports
//
export {
IState,
Selectors,
Operations,
};
export const Modules = [
// My module
getModule(),
];
module
reducer と middleware
情報を持つ object
他 module への依存関係は配列で表現
import React, {lazy} from 'react';
const CSWidget = lazy( () => import('./widgets/CS' /* webpackChunkName: "CSWidget" */) );
const FactoryWidget = lazy( () => import('./widgets/Factory' /* webpackChunkName: "FactoryWidget" */) );
const RepairWidget = lazy( () => import('./widgets/Repair' /* webpackChunkName: "RepairWidget" */) );
const Component: React.FC<IProps> = (props) => {
const { mode } = props;
return (
<div>
{mode === 'CS' && <CSWidget />}
{mode === 'Factory' && <FactoryWidget />}
{mode === 'Repair' && <RepairWidget />}
</div>
);
}
module 読込例
コンポーネントのタブを書くだけで
store も reducer も middleware も
利用可能に!
悩み
dispatch すると型情報が伝播しない
reducer や middleware で値を扱うときに型情報を使うには?
import actionCreatorFactory from 'typescript-fsa';
const actionCreator = actionCreatorFactory('ApplicationModule');
export const Actions = {
initialize : actionCreator('initialize'),
fetch : actionCreator.sync<IParam, IUser[], IError> ('fetch'),
}
action creator
import { reducerWithInitialState } from "typescript-fsa-reducers";
import { Actions } from './actions';
export interface IState {
users: IUser[];
}
const initialState = () : IState => {
users: [],
}
export default reducerWithInitialState( initialState() )
.case( Actions.fetch.done, (state, {result}) => {
return {...state, users: result}
})
reducer
import { middleware } from "typescript-fsa-redux-middleware";
import { Operations, Actions } from './operations';
export default middleware()
.case( Operations.fetchUsers, async ({dispatch, getState}, next, action) => {
const params = action.payload;
await dispatch( Actions.fetch.started(params) );
try {
const users = await fetch('URL');
dispatch( Actions.fetch.done({params, result: users}) );
} catch(error) {
dispatch( Actions.fetch.failed({params, error}) );
}
next(action);
})
middleware
関心空間の単位で
モジュール実装できる環境が整った!
今回紹介した技術を含めたサンプルを用意してあります
★ もお願いします!!!