当该属性成为地图时重用reducer

时间:2019-05-21 06:38:46

标签: typescript redux

我以前在我的应用程序中只有一个报告,所以我在应用程序状态下只有一个属性

现在我有一些不同的报告,每个用户对每个报告都有自己的设置。

export interface IApplicationState {
    ...

    reportsState: { // <- it was here
        reportSettings: IReportSettings; 
        ...
    }
    model: IModelState; 
}

export interface IModelState {
    dashboards: IDashboardModelsState;
    ...
}

export type IDashboardModelsState = { [id: number]: IDashboardModel };

export interface IDashboardModel {
    users: IUserModel[]
}

export interface IUserModel {
    userId: string;
    ...
    reportSettings:{ [reportType: number] : { // <-- and now it supposed to be here
        reportSettings: IReportSettings; 
        ...
    }
}

//store look like this
const store: Store<IApplicationState> = createStore(combineReducers({
        ...
        reportsState: reportsReducer,
        model: modelReducer,
    }
)

我要完成的工作是重用现有的reportReducer,但以某种方式将其连接到另一个reducer的ID索引属性。

1 个答案:

答案 0 :(得分:0)

我想出了解决方案,但我仍然不知道这是否好。

首先,我做了一个简单的商店(它只是在计算新状态)

export type Reducer<S> = (state: S, action: any) => S;

export class SimpleStore<S> {

    private state: S;
    private reducer: Reducer<S>;

    constructor(state: S, reducer: Reducer<S>) {
        this.state = state;
        this.reducer = reducer;
    }

    public setState(state: S) {
        this.state = state;
    }

    public getState(): S {
        return this.state;
    }

    public dispatch(action: any) {
        if (typeof action === "object") {
            const newState = this.reducer(this.state, action);
            this.setState(newState);
        } else if (typeof action ===  "function") {
            action(this.dispatch, this.getState); // becouse we have thunk
        }
    }
}

然后我获得了索引属性,并将reducer用作新的状态计算器。

case userActionTypes.USER_DASHBOARD_ACTION: {
            const userDashboardsIdAction = action as IPayloadIdAction<IPayloadAction<number | string>>;
            const targetDashboardState = state.dashboards[userDashboardsIdAction.id];
            const targetDashboardStore = new SimpleStore(targetDashboardState, dashboardReducer);

            if (!targetDashboardState) {
                targetDashboardStore.dispatch(initialAction());
            }
            targetDashboardStore.dispatch(userDashboardsIdAction.payload);
            const newTargetDashboardState = targetDashboardStore.getState();

            const newDashboardsStateToMerge = { };
            newDashboardsStateToMerge[userDashboardsIdAction.id] = newTargetDashboardState;

            const newDashboards = {
                ...state.dashboards,
                ...newDashboardsStateToMerge,
            };

            return {
                ...state,
                dashboards: newDashboards,
            };

        }

I have this ready to run on Github