【问题标题】:Why am I not getting any Data? Ngrx为什么我没有得到任何数据? Ngrx
【发布时间】:2019-08-13 13:12:31
【问题描述】:

我尝试在我的 Angular 应用程序中实现 Ngrx,但遗憾的是无法检索任何数据。任何帮助表示赞赏!

我在 property.component.ts 中尝试做的是在组件实例化时获取所有数据,并仅在 property.component.html 中显示数据。

property.component.ts

import {Component, OnInit} from '@angular/core';
import {select, Store} from '@ngrx/store';

import {Router} from '@angular/router';

@Component({
  selector: 'app-property',
  templateUrl: './property.component.html',
  styleUrls: ['./property.component.css']
})
export class PropertyComponent implements OnInit {

  properties$ = this._store.pipe(select('properties'));

  constructor(private _store: Store<any>, private _router: Router) {}

  ngOnInit() {
    this._store.dispatch({
      type: '[Property] Get Properties'
    });
    console.log(this.properties$);
  }

  navigateToProperty(id: number) {
    this._router.navigate(['property', id]);
  }

}

property.component.html

<p>test</p>
<p>{{properties$ | async}}</p>

property.service.ts

    import { Injectable } from '@angular/core';
    import {HttpClient, HttpHeaders} from '@angular/common/http';
    import { Observable } from 'rxjs';
    import {PropertyModel} from '../models/property.model';

    @Injectable({
      providedIn: 'root'
    })
    export class PropertyService {
      propertiesUrl = 'someapi';
      private httpOptions = {
        headers: new HttpHeaders({
          'Content-Type': 'application/json'
        })
      };

      constructor(private http: HttpClient) { }

      getProperties(): Observable<PropertyModel[]> {
        return this.http.get<PropertyModel[]>(this.propertiesUrl, this.httpOptions);
      }
    }

property.actions.ts

import { Action } from '@ngrx/store';
import {PropertyModel} from '../../models/property.model';


export const GET_PROPERTIES = '[Property] Get Properties';
export const GET_PROPERTIES_SUCCESS = '[Property] Get Properties Success';
export const SEARCH_PROPERTY = '[Property] Get Property';
export const SEARCH_PROPERTY_SUCCESS = '[Property] Get Property Success';

export class GetProperties implements Action {
  public readonly type = GET_PROPERTIES;
  constructor(public retrievedProperties: PropertyModel[]) {}
}

export class GetPropertiesSuccess implements Action {
  public readonly type = GET_PROPERTIES_SUCCESS;
  constructor(public retrievedProperties: PropertyModel[]) {}
}

export class GetProperty implements Action {
  public readonly type = SEARCH_PROPERTY;
  constructor(public searchId: string) {}
}

export type PropertyActions = GetProperties | GetPropertiesSuccess | GetProperty;

property.effects.ts

import {Injectable} from '@angular/core';
import {Actions, Effect, ofType} from '@ngrx/effects';

import {GET_PROPERTIES, PropertyActions} from '../actions/property.actions';
import {PropertyService} from '../../services/property.service';
import {mapTo} from 'rxjs/operators';


@Injectable()

export class PropertyEffects {

  @Effect()
  getProperties$ = this.actions$.pipe(
    ofType<PropertyActions>(GET_PROPERTIES),
    mapTo(this.propertyService.getProperties())
  );

  constructor(private actions$: Actions, private propertyService: PropertyService) {}

}

最后是我的property.reducers.ts

import {GET_PROPERTIES, GET_PROPERTIES_SUCCESS, PropertyActions} from '../actions/property.actions';
import {PropertyModel} from '../../models/property.model';

export function propertyReducer(properties: PropertyModel[] = [], action: PropertyActions): PropertyModel[] {
  switch (action.type) {
    case GET_PROPERTIES: {
      return [...action.retrievedProperties];
    }
    default: {
      return properties;
    }
  }
}

app.module.ts

import {BrowserModule} from '@angular/platform-browser';
import {NgModule} from '@angular/core';

import {AppComponent} from './app.component';
import {CustomerComponent} from './customer/customer.component';
import {HttpClientModule} from '@angular/common/http';
import {CustomMaterialModule} from './custom.material.module';
import {RouterModule, Routes} from '@angular/router';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {StoreModule} from '@ngrx/store';
import {PropertyComponent} from './property/property.component';
import {propertyReducer} from './store/reducers/property.reducers';

const appRoutes: Routes = [
  {
    path: 'customers',
    component: CustomerComponent,
    data: {title: 'Customer List'}
  },
  {
    path: 'property',
    component: PropertyComponent,
    data: {title: 'Property List'}
  },
  {
    path: '', // General redirect
    component: CustomerComponent,
    pathMatch: 'full'
  }
];

@NgModule({
  declarations: [
    AppComponent,
    CustomerComponent,
    PropertyComponent
  ],
  imports: [
    BrowserModule,
    RouterModule.forRoot(appRoutes),
    HttpClientModule,
    BrowserAnimationsModule,
    CustomMaterialModule,
    StoreModule.forRoot(propertyReducer)
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule {}

【问题讨论】:

  • 您的效果应该发送成功,然后将返回的数据映射到您的状态。现在,您正在调用您的服务,但返回的数据并未映射到您的状态,因为在效果之前调用了 reducer
  • 在我的效果之前我的减速器是如何被调用的?

标签: angular typescript web frontend ngrx


【解决方案1】:

工作stackblitz example

不要忘记调度成功和错误操作并减少它们。 还将mapTo 更改为switchMapTo

@Effect()
getProperties$ = this.actions$.pipe(
  ofType<PropertyActions>(GET_PROPERTIES),
  switchMapTo(this.propertyService.getProperties().pipe(
    map(props => new GetPropertiesSuccess(props)),
   // catch error here
   // catchError(error => of(new GetPropertiesError(error))),
    ),
  ),

);

在你的 reducer 中,听正确的类型

case GET_PROPERTIES_SUCCESS: {
  return [...action.retrievedProperties];
}

为了清楚起见,从 GetProperties 中删除 retrievedProperties - 该操作没有任何检索到的道具。应该使用成功操作来传递它们。

在您的应用模块中更改减速器设置,不要忘记导入效果:

imports: [
BrowserModule,
RouterModule.forRoot(appRoutes),
HttpClientModule,
BrowserAnimationsModule,
// change this
StoreModule.forRoot({properties: propertyReducer}),
// this is needed
EffectsModule.forRoot([PropertyEffects])
],

可选:在您的PropertyComponent 中,将调度的操作更改为GetProperties 类的实例。这就是它应该使用的方式。

 this._store.dispatch(new GetProperties());

【讨论】:

  • 我试过你的代码,但本地主机似乎只是不断加载。
  • 在不实际运行的情况下很难调试整个代码。如果您提供 stackblitz 示例,我会看看。
  • 我又添加了一个东西,app.module.ts,如果有帮助的话。在此期间,我将尝试设置堆栈闪电战
  • 好吧,我去的兔子洞,你的代码中的错误越来越多。你应该去尝试一个 NGRx 教程。这里有很多误解。
  • 我搞定了。我扩展了我的答案,所以它拥有一切。祝你编码好运。 stackblitz.com/edit/angular-d5aypp
猜你喜欢
  • 2022-01-11
  • 1970-01-01
  • 1970-01-01
  • 2015-06-26
  • 1970-01-01
  • 1970-01-01
  • 2011-11-27
  • 2021-12-15
  • 1970-01-01
相关资源
最近更新 更多