代码之家  ›  专栏  ›  技术社区  ›  antonyboom

NgRX store select返回存储状态而不是数据

  •  6
  • antonyboom  · 技术社区  · 8 年前

    我正在尝试将ngrx v4实现到我的angular项目中,并努力从ngrx存储中获取数据。我根据提供的api文档编写了Actions、Reducer和Effects github page 在我看来,一切都是正确的,但我得到的不是这样的数据存储状态:

    enter image description here

    因此,如果有人能帮我找出我的错误所在,我将不胜感激。提前谢谢。下面是我的代码

    界面ts

    export interface Category {
      id?: number;
      name: string;
      used: boolean;
    }
    

    行动。ts

    import { Action } from '@ngrx/store';
    import {Category} from '../categories';
    
    export const GET_CATEGORIES  = '[Category] Get data';
    export const GET_CATEGORIES_ERROR = '[Category] Get data error';
    export const GET_CATEGORIES_SUCCESS  = '[Category] Get data success ';
    
    export class GetCategories implements Action {
      readonly type = GET_CATEGORIES;
    }
    export class GetCategoriesError implements Action {
      readonly type = GET_CATEGORIES_ERROR;
    }
    export class GetCategoriesSuccess implements Action {
      readonly type = GET_CATEGORIES_SUCCESS;
      constructor(public payload: Category[]) { }
    }
    
    export type All = GetCategories | GetCategoriesSuccess | GetCategoriesError
    

    减速器。ts

    import * as CategoriesActions from './categories.actions';
    import {Category} from '../categories';
    
    export type Action = CategoriesActions.All;
    
    export function categoriesReducer (state: Category[], action: Action) {
    
      switch (action.type) {
    
        case CategoriesActions.GET_CATEGORIES: {
          return state;
        }
    
        case CategoriesActions.GET_CATEGORIES_ERROR: {
          return state;
        }
    
        case CategoriesActions.GET_CATEGORIES_SUCCESS: {
          return action.payload;
        }
    
        default: {
          return state;
        }
      }
    }
    

    影响。ts

    ...
    import {CategoriesService} from './categories.service';
    
    @Injectable()
    export class CategoriesEffects {
    
      @Effect() getCategories$: Observable<Action> = this.actions$
        .ofType('GET_CATEGORIES')
        .mergeMap(action => this.categoriesService.getCategories()
          .map(data => ({type: 'GET_CATEGORIES_SUCCESS', payload: data }))
          .catch(() => of({ type: 'GET_CATEGORIES_ERROR', payload: {message: 'Oops something is wrong'} }))
        );
    
      constructor(
        private actions$: Actions,
        private categoriesService: CategoriesService
      ) {}
    }
    

    组成部分ts

    interface CategoryState {
      categories: Category[]
    }
    
    @Component({
      selector: 'app-categories',
      templateUrl: './categories.component.html',
      styleUrls: ['./categories.component.css'],
    })
    
    export class CategoriesComponent implements OnInit {
    
      categories$: Observable<Category[]>;
    
      constructor(private store: Store<CategoryState>) {
    
        console.log(this.categories$) // undefined
    
        this.categories$ = this.store.select('categories');
    
        console.log(this.categories$) // store state
      }
    
      ngOnInit() {
        this.getCategories()
      }
    
      getCategories () {
        this.store.dispatch({ type: 'GET_CATEGORIES' });
      } 
    }
    

    单元

    @NgModule({
      imports: [
        ...
        StoreModule.forRoot({ categories: categoriesReducer }),
        EffectsModule.forRoot([CategoriesEffects]),
      ],
      declarations: [ CategoriesComponent ],
      providers:    [ CategoriesService ],
      entryComponents: []
    })
    export class CategoriesModule {}
    
    3 回复  |  直到 8 年前
        1
  •  4
  •   ryanrain    8 年前

    这并不是对antonyboom的具体问题的回答,而是根据问题的标题为其他人提供了一个有用的提示:似乎是NGRX的商店。如果select在您查询的路径上找不到数据,它将返回可观察的存储作为默认值。想想Apache 404错误。

    我不得不修改我的类型转换,以确保typescript没有强制执行错误的存储结构。具体来说,请注意,为减速器中的第一个参数指定的接口与注入组件的接口不同。

    型号,减速器:

    export interface AppState {
      textinput: string;
      integerVariable: number;
    }
    export interface State {
      app: AppState;
    }
    
    export function reducerFunction (
      state: AppState,
      action: Actions
    ) {
      switch (action.type) {
        ...
      }
    }
    

    应用程序。单元ts:

    StoreModule.forRoot({
      app: reducerFunction
    })
    

    应用程序。组成部分ts

    export class AppComponent {
    constructor(private store: Store<State>) {
        this.currentSlide = store.select(s => s.app.textinput);
    }
    ...
    }
    
        2
  •  2
  •   Aravind    8 年前

    因为您正在使用 ngrx/store : 4.1

    • 您应该有一个减速机工厂,将减速机注入StoreModule

      import {ActionReducerMap} from '@ngrx/store';
      import {Category} from '../categories';
      import * as categoryReducer from './categories.reducer';
      
      export interface CategoryState {
        categories: Category[]
      }
      
      export interface AppStates {
        categoryState: CategoryState;
      }
      
      export const categoryReducers: ActionReducerMap<AppStates> = {
        categoryState: categoryReducer.reducer
      };
      
    • 使用减速机工厂注入模块,如下所示,

      StoreModule.forRoot(categoryReducers)
      import {categoryReducers} from './store/categories.reducer.factory';
      
    • 您的构造函数应该采用 AppStates 作为的类型 Store

      constructor(private store: Store<AppStates>){}
      
    • 你的效果应该是

      @Effect() 
      getCategories$: Observable<Action> = this.actions$
          .ofType(CategoriesActions.GET_CATEGORIES)
          .mergeMap(action => this.categoriesService.getCategories()
                .map(data => ({type: CategoriesActions.GET_CATEGORIES_SUCCESS, payload: data }))
                .catch(() => of({ type: CategoriesActions.GET_CATEGORIES_ERROR, payload: {message: 'Oops something is wrong'} }))
          );
      
        3
  •  1
  •   Amin Saqi    7 年前

    减速器导入部分中提供的名称必须与 State

    存储:

    export interface AppState {
      logs: string[];
    }
    
    export interface AppStore{
      appState: AppState; // (1)
    }
    

    应用程序。单元ts导入:

    StoreModule.forRoot({
      appState: reducerFunction // (2)
    })
    

    所以,(1)和(2)( appState )必须相同。