EchtFettigerKeks
EchtFettigerKeks

Reputation: 1893

How to reload data when "hard navigate" with ngrx/store?

In my application I retrieve all data in the "Items-Overview-Component" in the constructor. (router path: "/items").

// Items-Overview-Component

constructor(private store: Store<fromReducer.State>) {
    this.store.dispatch(loadItems());
}

When clicking on an item entry, I navigate to "/items/:id". Then I retrieve the details from the store using the :id.

// Item-Details-Component

constructor(private store: Store<fromReducer.State>) {
    this.item$ = this.store.pipe(select(getItemDetails));
}

So far a very clear vanilla use case for an Angular project.

However, if the user navigates "hard" to a URL with a specific item (e.g. "/items/741"), then the store is empty and no details can be retrieved.

How can I reload the data in NGRX "on demand"? Is there perhaps a one-time lifecycle hook that I should react to here?

BTW: I also use @ngrx/router-store

Upvotes: 2

Views: 1358

Answers (1)

JoannaFalkowska
JoannaFalkowska

Reputation: 3677

The pattern you want is most likely to use a guard on the /items route, instead of relying on the Items-Overview-Component to trigger loading items.

It could look like:

@Injectable({
  providedIn: 'root',
})
export class ItemsGuard implements CanActivate {
  constructor(
    private store: Store<AppState>
  ) {}

  public canActivate(): Observable<boolean> {
    this.store.dispatch(loadItems()); // immediately trigger loading items

    return this.store.select(getItems).pipe(
      filter(items => !!items && items.length) // wait until the selector emits some non-empty items list
      mapTo(true) // as soon as the items are present, allow the navigation event to complete
    );
  }
}

Then you can use it in your routes file like this:

    path: 'items',
    canActivate: [ItemsGuard],
    ....
    children: [ 
      // '/:id' route goes here
    ]

Since items/:id is configured as a child route of /items, ItemsGuard will trigger in both cases, even if after page refresh you directly enter /items/123 without ever entering /items.

Upvotes: 2

Related Questions