Resubscribing to NGRX Effect loading old data

Discussão em 'Angular' iniciado por jProg2015, Março 2, 2025.

  1. jProg2015

    jProg2015 Guest

    I'm having an odd interaction with NGRX and Routing whereby when I revisit a page I have previously been on and subscribe to an Effect it gets the data twice; but this only happens when the page I have visited in between does not do a dispatch. For example:

    Page A subscribes and dispatches. Page B subscribes and dispatches. Page C subscribed and does not dispatch.

    If I were to load Page A, then B then A; everything works as expected.

    If I were to load Page A, then C, then A; the second time I visit page A the data gets loaded twice (once from some sort of invisible cache then once from the API).

    My services all look like this:

    @Injectable({
    providedIn: 'root',
    })
    export class ForumService {
    private store = inject(Store);
    private httpClient = inject(HttpClient);

    getCategories(page: number): Observable<PaginatedResponse<ForumCategoryResponse, 'categories'>> {
    let token: string | null = null;
    this.store
    .select(selectToken)
    .pipe(take(1))
    .subscribe((t) => {
    token = t;
    });

    return this.httpClient.get<PaginatedResponse<ForumCategoryResponse, 'categories'>>(
    `${environment.baseApiUrl}/forum/categories?page=${page}`,
    {
    headers: {
    Authorization: `Bearer ${token}`,
    },
    }
    );
    }
    }


    My effects all look like this:

    @Injectable()
    export class ForumEffects {
    private actions$ = inject(Actions);
    private forumService = inject(ForumService);

    getCategories$ = createEffect(() => {
    return this.actions$.pipe(
    ofType(getCategories),
    exhaustMap((action) => {
    return this.forumService
    .getCategories(action.page)
    .pipe(
    map((response) => getCategoriesSuccess(response)),
    catchError((error: ApiError) => of(getCategoriesFailure(error))),
    );
    })
    );
    });
    }


    And my components all look like this and all implement a pipe with takeUntil:

    @Component({
    selector: 'app-forum-categories',
    imports: [ContainerComponent, HorizontalRuleComponent, NgFor, RouterLink],
    templateUrl: './forum-categories.component.html',
    })
    export class ForumCategoriesComponent implements OnInit, OnDestroy {
    private readonly store = inject(Store);
    private readonly actionsSubject = inject(ActionsSubject);
    destroy$ = new Subject<boolean>();
    forumCategories: ForumCategoryResponse[] = [];
    currentPage = 1;
    morePages = true;

    ngOnDestroy() {
    this.destroy$.next(true);
    this.destroy$.complete();
    }

    ngOnInit(): void {
    this.actionsSubject
    .pipe(ofType(getCategoriesSuccess))
    .pipe(takeUntil(this.destroy$))
    .subscribe((action) => {
    if (action.categories !== null) {
    this.forumCategories.push(...action.categories);
    }
    this.currentPage = action.page;
    this.morePages = action.morePages
    });

    this.store.dispatch(getCategories({ page: 1 }));
    }
    }


    So to reiterate; with the above code this.forumCategories.push(...action.categories); will get called with the old data, then the dispatch happens, then it will get called again and I get two sets of data. It doesn't happen on first load and it doesn't happen if I've visited a page which has done another dispatch call.

    Pretty new to NGRX so I wouldn't be surprised if I'm doing something wrong but I don't understand it because in this case the data isn't even saved in the store.

    Continue reading...

Compartilhe esta Página