错误TypeError:无法读取未定义的属性'concat'

时间:2019-05-09 10:09:44

标签: angular ngrx

在组件内部,我调用此函数是为了在向下滚动列表时获取更多数据:

  onScroll(event) {
    if (this.shouldGetData(event.srcElement)) {
      this.store.dispatch(new StartAppendRoutesList());
    }
  }
  /* support methods */

  shouldGetData(targetEventElement) {
    return this.scrollAskForData(targetEventElement) && !this.alllistAlreadyFetched;
  }

  scrollAskForData(targetEventElement): boolean {
    const scrollPercentage = ((targetEventElement.clientHeight + targetEventElement.scrollTop) / targetEventElement.scrollHeight) * 100;
    return scrollPercentage > constants.SCROLL_PERCENTAGE_THRESOLD_TO_GET_DATA;
  }

除了我的副作用外,我还有以下优点:

  @Effect()
  appendRoutes = this.actions$.pipe(
    ofType(RoutesListActionTypes.StartAppendRoutesList),
    switchMap((action: StartAppendRoutesList) => this.service.getRoutes(fromRoot.initialStateRouteList.currentOffset)
      .pipe(
        switchMap(result => of(new EndAppendRoutesList(result))),
        catchError(err => of(new OnError(err.message)))
      ))
  );

我的动作如下:

  StartAppendRoutesList = '[routes] Starting Adding More items to route list',
  EndAppendRoutesList = '[routes] Ending Adding More items to route list',

并具有以下代码:

export class EndAppendRoutesList implements Action {
  readonly type = RoutesListActionTypes.EndAppendRoutesList;
  payLoad: RouteList;

  constructor(payLoad: RouteList) {
    this.payLoad = payLoad;
  }
}

export class StartAppendRoutesList implements Action {
  readonly type = RoutesListActionTypes.StartAppendRoutesList;
}

我的减速器是这样的:

case RoutesListActionTypes.StartAppendRoutesList:
  return {
    ...state,
    processingRoute: true,
  };
case RoutesListActionTypes.EndAppendRoutesList:
  const queryResult = action;
  return {
    ...state,
    processingRoute: false,
    currentOffset: state.currentOffset + 5,
    routesList: {
      results: state.routesList.results.concat(queryResult.payLoad.results)
    }
  };

现在,乍一看,当我应用偏移量以检索一定数量的数据时,或者如果我选择在服务中检索整个列表,一切都会很好:

  getRoutes(offset: number): Observable<any> {
    const numberToRetrieve = 5;
    const routes = configUrl.routeBaseUrl["routes"]["results"];
    return of(routes.slice(offset, numberToRetrieve));
  }

但是一旦到达列表末尾,它就会开始提示我这个错误: enter image description here

显示的错误是在我的reducer内的concat方法上:

routesList: {
  results: state.routesList.results.concat(queryResult.payLoad.results)
}

我试图通过创建一种方法来寻找解决方案,该方法将在我的fetched indicator方法内部返回一个createStateSubscriptions,该方法在ngOnInit内部被调用,如下所示:

  alllistAlreadyFetched = false;
  ngOnInit() {
    // state subscriptions
    this.createStateSubscriptions();
    // attaching listeners
    this.createEventScrollSubscription();
    // getting initial data
    this.store.dispatch(new StartLoadRoutesList());
  }

  /* subscriptions and observables creation methods*/
  createStateSubscriptions() {
    // state observable use directly in view through async pipe
    this.listObservable$ = this.store
      .select((state: RoutesListState) => state);

    // all routes fetched indicator
    this.listStateSubscription$ = this.store
      .select(allListItemsAlreadyFetchedValidators)
      .subscribe((allRoutesFetched: boolean) => {
          this.alllistAlreadyFetched = allRoutesFetched;
      });
  }

我的allListItemsAlreadyFetchedValidators selector就像这样:

export const allListItemsAlreadyFetchedValidators = createSelector(
  selectRoutesList,
  state => state.routes.currentOffset,
  (currentOffset, TotalRoutes) => currentOffset.currentOffset >= TotalRoutes
);

但是随后我在.select(allListItemsAlreadyFetchedValidators)的组件中遇到另一个错误,如下所示:

ERROR in side-list/side-list.component.ts(43,15): error TS2345: Argument of type 'MemoizedSelector<State, boolean>' is not assignable to parameter of type '"routesList" | "processingRoute" | "processingDetail" | "currentOffset" | "selectedRouteItemId" | "selectedRouteItemData" | "errorMessage"'.
  Type 'MemoizedSelector<State, boolean>' is not assignable to type '"errorMessage"'.

这是我的HTML:

<div class="routes-container">
  <div class="wrapper-scroll-y grid-scrollbar">
    <header class="header" role="banner">
      <h1 class="logo">
        <a><span>Routes :</span></a>
        <mat-icon class="icon">add</mat-icon>
      </h1>
      <div class="nav-wrap">
        <nav class="main-nav" role="navigation">
          <ul class="unstyled list-hover-slide" *ngFor="let route of (listObservable$|async).routes.routesList">
            <li (click)= "onListItemSelected($event, route.id)"><a>{{route.name}}</a></li>
          </ul>
        </nav>
      </div>
    </header>
  </div>
  <app-loader-indicator [show]="(listObservable$|async).processingRoute"></app-loader-indicator>
</div>

1 个答案:

答案 0 :(得分:1)

如果您的state.routesList.results未定义或不是数组,则将面对该错误。要解决它,您必须在concat方法之前检查它。如果不是数组或未定义,则可以直接将结果设置为queryResult.payLoad.results

routesList: {
  results: (state.routesList.results && state.routesList.results instanceOf Array)? state.routesList.results.concat(queryResult.payLoad.results) : queryResult.payLoad.results
}