Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@ngrx select specific slice of state from store when using a smart component recursively

I'm kinda new to ngrx and I've encountered this little problem I haven't figured out how to solve yet.

Basically I have a ListComponent that renders an array of ListItemComponents from a ngrx store.

@Component({ 
  ...
  template: `
    <list-item *ngFor="let item of item$ | async" [data]="item">
    </list-item>
  `
})
export class ListComponent implements OnInit {
  item$: Observable<ListItem>;
  constructor(private store: Store<ListState>) {}

  ngOnInit() {
    this.item$ = this.store.select(selectListItems);
  }
}

Now, inside ListItemComponent, under some specific circumstances I want to render another ListComponent where I can add items to, however this doesn't work as I get a Maximum call stack size exceeded error.

My guess is, and correct me if I'm wrong, since the nested ListComponent is accessing the same slice of state as the root ListComponent, its just trying to nest and render the same list over and over and over again into infinity.

So here's the question, how should I compose my selectors in order to provide the correct entry point in the state tree to each nested ListComponent?


Edit

Here's a working stackblitz project, now the logic in my app to render a List inside a ListItem is different but the problem is the same.

like image 250
Osman Cea Avatar asked Jan 06 '18 10:01

Osman Cea


1 Answers

I think you're right:

My guess is, and correct me if I'm wrong, since the nested ListComponent is accessing the same slice of state as the root ListComponent, its just trying to nest and render the same list over and over and over again into infinity.

Try updating ListComponent to accept a component input variable of ListItemComponent. See working example https://stackblitz.com/edit/angular-ngrx-recursive-components-7mzncj

In that example, the 5th ListItemComponent also renders a ListComponent. However, when clicking the "add element to list" button on that 5th ListItemComponent, the code is still adding the new elements to the parent list. I'm guessing you'll want to update your logic for how that is handled. Not sure what you're trying to accomplish.

The core problem is that the list is generating itself. So if a list generates another list, you run into the recursive problem. By using component input variables, you can stop the list from generating itself and eliminate the recursive problem.

Update:

I came to this answer on my own, but I just noticed that @FanCheung, in the comments, previously proposed what is basically this solution.

like image 148
John Avatar answered Oct 17 '22 04:10

John