This is the interface of the product
export interface Product{
id?:string,
name:string,
price:string;
quantity:string;
tags:Tags[];
description:string;
files: File[];
}
In my home.component.ts file I have this
export class HomeComponent implements OnInit {
constructor(
private store:Store<fromRoot.AppState>
) { }
products$!: Observable<Product[]>;
products_list! :Product[];
ngOnInit(): void {
this.store.dispatch(new productActions.LoadProducts());
^^^^This function calls the loadproducts$ from effect.ts
this.products$ = this.store.pipe(select(fromProduct.getCreatedProducts));
}
}
products$ is an obseravale now to display this, I use Async | json .Below is my html code.
<div *ngFor = "let p of products$ | async">
<h1>
{{p.name}}
</h1>
</div>
Here I am attesting action.ts
export enum UserActionTypes{
LOAD_CREATED_PRODUCTS = '[User] Load Created Products',
LOAD_CREATED_PRODUCTS_SUCCESS = '[User] Load Created Products Success',
LOAD_CREATED_PRODUCTS_FAIL = '[User] Load Created Products Fail'
}
export class LoadProducts implements Action{
readonly type = UserActionTypes.LOAD_CREATED_PRODUCTS
}
export class LoadProductsSuccess implements Action{
readonly type = UserActionTypes.LOAD_CREATED_PRODUCTS_SUCCESS
constructor(public payload:Product[]){}
}
export class LoadProductsFail implements Action{
readonly type = UserActionTypes.LOAD_CREATED_PRODUCTS_FAIL
constructor(public payload:string){}
}
export type action = LoadProducts | LoadProductsSuccess | LoadProductsFail ;
Here is my product.reducer.ts
export interface SoldProductState extends EntityState<Product>{
selectedProductId: string,
loading:boolean,
loaded:boolean,
error:string
}
export const productAdapter:EntityAdapter<Product> = createEntityAdapter<Product>({
selectId:Product=>Product.id
});
export const defaultProduct:SoldProductState={
ids:[],
entities:{},
selectedProductId:"",
loading:false,
loaded:false,
error:""
}
export const initialState = productAdapter.getInitialState(defaultProduct);
export function productReducer(
state = initialState,
action:productActions.action
):SoldProductState{
Here is my LoadCreatedProduct
switch(action.type){
case productActions.UserActionTypes.LOAD_CREATED_PRODUCTS:{
return {
...state,
loading:true,
loaded:false
};
}
Here is my LoadCreatedProductSuccess
case productActions.UserActionTypes.LOAD_CREATED_PRODUCTS_SUCCESS:{
return productAdapter.addMany(action.payload,{
...state,
entities:{},
loaded:true,
loading:false
});
}
default:{
return state;
}
}
}
Here I am adding the effect.ts
@Effect()
loadproducts$:Observable<Action> = this.action$.pipe(
ofType<productActions.LoadProducts>(
productActions.UserActionTypes.LOAD_CREATED_PRODUCTS
),
mergeMap((actions:productActions.LoadProducts)=>
this.product_service.getCreatedProducts().pipe(
map(
(products:Product[])=>
new productActions.LoadProductsSuccess(products)
),
catchError(err=>of(new productActions.LoadProductsFail(err)))
))
)
Now, If I load the page every thing is displayed properly as shown below
If I navigate to another page and comes back the list doubles as shown below
If I visit another page n times the list will be displayed n times.
But if I reload the page it works fine. I am a beginner and do not know how to tackle this problem. I hope I am able to explain my problem. Thanking you.
addMany
(productAdapter.addMany) append the new items to the already existing items, which causes duplication in your data.
use setAll
instead of addMany
to replace all the existing items with the new ones: