Angular2状态管理和@ ngrx / store

时间:2016-10-20 17:51:41

标签: angular store ngrx

我正在使用ngrx / store为我的应用程序编写reducer。

以下是我的应用程序状态的布局:

{
    project: {
        name: string
        tasks: Array<Task>
    }
}

with:

interface Task {
    name: string
}

我正在尝试在单独的文件中编写干净的reducer。

以下是我目前正在使用的解决方案:

project.reducer.ts

import {tasksReducer} from './tasks.reducer';

const projectReducer = (state:Project = null, action: Action): Project => {
    switch (action.type) {
        case 'CREATE_PROJECT':
            return {
                name :'New project',
                tasks: []
            };
    };

    state.tasks = tasksReducer( state.tasks, action );

    return state;
}

tasks.reducer.ts

export const tasksReducer = (state:Array<Task> = [], action: Action): Array<Task> => {
    switch (action.type) {
        case 'ADD_TASK':
            return [...state, { name: 'New task' ];
        default:
            return state;
    };
}

使用以下商品提供商店:

StoreModule.provideStore( combineReducers([{
    project: projectReducer
}]) );

如果我想在项目中添加其他字段,例如标记字段:

{
    project: {
        name: string,
        tasks: Array<Task>,
        tags: Array<Tags>
    }
}

我可以创建一个单独的 tags.reducer.ts ,并使用相同的方法创建相应的reducer。

这种方法出了什么问题?

我很确定我遇到了有关应用程序状态不可变性的麻烦。

例:

  • 我调度CREATE_PROJECT动作,我得到一个新状态,一切正常。
  • 然后我发送ADD_TASK动作。
    • tasksReducer本身返回一个全新的任务数组,但主要的应用程序状态是变异的......这不好!

在您的意见中,解决此问题的最佳方法是什么?

更一般地说:

随着我的项目对象越来越大,越来越多的领域,我该怎么做:

  • 保持减速机分离
  • 使减速器在“主”减速器的隔离子部件上运行
  • 保持我的状态不变

我很乐意与大家分享这些意见!

1 个答案:

答案 0 :(得分:2)

首先围绕你的projectReducer做一些评论。 您在switch语句中缺少默认大小写,这非常重要。 (见http://blog.kwintenp.com/how-to-write-clean-reducers-and-test-them/#defaultcase)。所以将它添加到该reducer:

default:
   return state;

其次,在调用taskReducer时,你正在做一些奇怪的事情。调用projectReducer时,您正在执行的操作始终调用taskReducer。实际上,当你想要调用taskReducer时,只要它是一个动作,他就可以做一些事情:

case 'ADD_TASK':
   // call it here

您也在覆盖当前状态的任务属性。正如你所说,你正在改变你的状态,这是一个明确的事情要避免。您可以利用Object.assign运算符来完成您想要的操作(整个修复):

const projectReducer = (state:Project = null, action: Action): Project => {
    switch (action.type) {
        case 'CREATE_PROJECT':
            return {
                name :'New project',
                tasks: []
            };
        case 'ADD_TASK':
            return Object.assign({}, state, {tasks: tasksReducer( state.tasks, action )};
        default:
            return state;
    };
}

现在,当您将任务更改为任务时,您正在创建一个新的Project对象,这就是您想要的。

我建议你阅读我的整篇博文,了解如何以干净的方式编写减速器。

你的一般性问题可能有详细的答案,但我想这会跳过这一点。下面简短的答案。

保持减速器分离

- &GT;您正在使用combineReducers辅助方法,这是让您的Reducer分离的好方法。

让减速机在“主要”的隔离子部分上运行。减速器

- &GT;与上述相同

让我的状态保持不变

- &GT;按照我的博客文章中的提示,在需要时使用Object.assign和spread运算符。

相关问题