4

can you please tell me how to fetch data from server first time only and show to screen . but if user come again or if component again loaded it get data from store .I am using redux with ngrx .

I made a sample application in which i have two button home screen and new screen home screen I show list which is coming from server .when i click new screen button and come back to home screen it again it server and get the data.I don't want to hit again.I want to get data from store .How i will get it

here is my code

(don't open this link in chrome stackblitz have issue in chrome )

export class ListComponent implements OnInit {

 products$: Observable<Product[]>;
  constructor(private productService: ProductService,
              private store: Store<fromApp.ProductState>,
              private router : Router
              ) {}

 ngOnInit() {
    this.store.dispatch(new productActions.Load());
    this.products$ = this.store.pipe(select(fromProduct.getProducts))
  }
}
Anuradha Gunasekara
  • 6,553
  • 2
  • 27
  • 37
user5711656
  • 3,310
  • 4
  • 33
  • 70
  • Possible duplicate of [What is the correct way to share the result of an Angular Http network call in RxJs 5?](https://stackoverflow.com/questions/36271899/what-is-the-correct-way-to-share-the-result-of-an-angular-http-network-call-in-r) – jonrsharpe Jul 03 '18 at 09:57
  • this is not dublicate Question – user5711656 Jul 03 '18 at 10:06
  • That's not a useful assertion. Why not? What did you learn from reading that question and what do you still want to know? Did you try it? What are the specifics of your situation that prevented it from working? [Edit] the question. – jonrsharpe Jul 03 '18 at 10:08
  • first they are not using `ngrx` or store .secondly how I will check data is present on store or not – user5711656 Jul 03 '18 at 10:10
  • 1. Does that matter? You're talking about caching the server data, it doesn't necessarily matter where that does within the app. 2. I'd imagine the relevant documentation tells you how to check whether something is in the store. – jonrsharpe Jul 03 '18 at 10:11
  • i got the answer thanks for help – user5711656 Jul 03 '18 at 10:14

1 Answers1

5

In your case, I would probably have a property inside my store that indicates whether the data was already loaded or not, e.g. loaded. The first time you dispatch the action that goes and fetches the data in your Effect, when the data returns you would also set this loaded property to true. The default value would be false. Inside your Effect you could then use withLatestFrom and select the loaded property. If it's set to true, don't do anything, if it's set to false, go and fetch the data.

First of all, change your ProductState and introduce a loaded property:

export interface ProductState {
  toggleCheckBox: boolean,
  products: Product[],
  loaded: boolean;
  error: string
}

const initialState: ProductState = {
  toggleCheckBox: true,
  products: [],
  loaded: false,
  error: ''
};

In your reducer, on LoadSuccess, set the loaded property to true:

case ProductActionTypes.LoadSuccess:
  return {
    ...state,
    products: [...action.payload],
    loaded: true,
    error: ''
  }

Now, inside your Effect, check for the loaded property and then fetch the data depending on its value:

@Effect()
loadProduct$: Observable<Action> = this.action$.pipe(
  ofType(productAction.ProductActionTypes.Load),
  withLatestFrom(this.store.pipe(select(fromProduct.getLoaded))),
  switchMap(([, loaded]) => {
    if (loaded) {
      return empty();
    }

    return this.productService.getProducts().pipe(
      map((products) => {
        return new productAction.LoadSuccess(products)
      }),
      catchError(err => of(new productAction.LoadFail(err)))
    )
  })
);

This means, your Effect would only fetch the data when it's not loaded already, which is indicated by the loaded property on your ProductState.

Check out this StackBlitz to see it in action. Open up the Network tab the dev console to verify that the request is only fired once and after that it's being "cached" due to the loaded property.

LordTribual
  • 4,219
  • 2
  • 28
  • 38
  • Nice, like this answer and helped me, I did find however that using `filter` after `withLatestFrom` was a better solution, and I got errors returning `empty()` so removed that, other than that great job – Neil Stevens Nov 08 '18 at 10:39