簡體   English   中英

Angular2狀態管理和@ ngrx / store的正確用法

[英]Angular2 state management and the correct usage of @ngrx/store

我正在使用ngrx / store為我的應用程序編寫減速器。

這是我的應用程序狀態的布局:

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

with:

interface Task {
    name: string
}

我正在嘗試在單獨的文件中編寫干凈的減速器。

這是我當前正在使用的解決方案:

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

任務減少器

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>
    }
}

我可以創建一個單獨的tag.reducer.ts並使用相同的方法來創建相應的reducer。

那么這種方法有什么問題呢?

我敢肯定,我遇到了有關應用程序狀態不變性的麻煩。

范例:

  • 我調度了CREATE_PROJECT動作,我得到了一個新的狀態,一切正常。
  • 然后我調度ADD_TASK動作。
    • taskReducer本身會返回一個全新的任務數組,但是主應用程序狀態卻發生了變化……這不好!

您認為解決此問題的最佳方法是什么?

更普遍:

隨着我的項目對象隨着越來越多的領域而變得越來越大,我該怎么做:

  • 減速器分開
  • 使減速器在“主”減速器的隔離子部分上運行
  • 保持我的狀態不變

我很樂意分享有關此事的意見!

首先,圍繞您的projectReducer發表一些評論。 您在switch語句中缺少默認情況,這非常重要。 (請參閱http://blog.kwintenp.com/how-to-write-clean-reducers-and-test-them/#defaultcase )。 因此,將其添加到該減速器中:

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對象。

我建議您閱讀我的整個博客文章,以獲取有關如何以簡潔的方式編寫reducer的一些指導。

您的一般性問題可能會有詳盡的答案,但我想這將跳過這一點。 以下是一些簡短的答案。

減速器分開

->您正在使用CombineReducers輔助方法,這是使減速器分離的好方法。

使減速器在“主”減速器的隔離子部分上運行

->同上

保持我的狀態不變

->按照我的博客文章中的提示進行操作,並在需要時使用Object.assign和散布運算符。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM