web-dev-qa-db-fra.com

Comment créer un sélecteur pour sélectionner un élément par identifiant dans ngrx store

J'ai lu la documentation de ngrx store sur les sélecteurs et je dois trouver un moyen de créer un sélecteur afin de sélectionner un élément par son identifiant. Je peux déjà le faire dans le cadre de l'abonnement au magasin lorsque j'obtiens tous les éléments du sélecteur selectAllItems, mais je dois comprendre comment sélectionner un élément spécifique dans une liste d'éléments du magasin. Ma raison principale est que createSelector offre des gains de performance dont j’aime tirer profit.

Voici mon code:

import { AppState, Item } from '../../shared/models/index';
import { createSelector } from '@ngrx/store';

export const selectItems = (state: AppState) => state.eventsState;

export const selectAllItems = createSelector(selectItems, (allItems: { items: Item[] }) => {
  if (allItems && allItems.items) {
   return allItems.items.filter((item: Item) => (!item.active && !item.closed));
  } else {
    return allItems.items;
  }
});

Ensuite, dans mon contrôleur, je filtre par identifiant pour obtenir l'élément souhaité:

this.store.select(selectors.selectAllItems)
  .filter(data => data !== null)
  .subscribe(allItems => {
    this.item = allItems.filter(item => {
      return item.id === this.navParams.data.id;
    });
  });

J'aimerais pouvoir créer un sélecteur pour cet élément spécifique et l'utiliser de la manière suivante:

this.store.select(selectors.selectItemById(this.navParams.data.id))
  .filter(data => data !== null)
  .subscribe(selectedItem => {
    this.item = selectedItem;
  });

Toute aide serait appréciée.

6
Oleksiy Kononenko

Après quelques recherches, j'ai résolu mon propre problème. J'ai utilisé la fonction d'usine pour obtenir le sélecteur selectItemById souhaité. Voici mon nouveau sélecteur:

import { AppState, Item } from '../../shared/models/index';
import { createSelector } from '@ngrx/store';

export const selectItems = (state: AppState) => state.eventsState.items;

export const getItemById = (id) => createSelector(selectItems, (allItems) => {
  if (allItems) {
    return allItems.find(item => {
      return item.itemId === id;
    });
  } else {
    return {};
  }
});

Ensuite, tout ce que je dois faire dans mon contrôleur est d’appeler ce sélecteur et de lui transmettre l’identifiant de l’article souhaité pour le faire sortir du magasin:

import * as selectors from '../../app/store/selectors';

this.store.select(selectors.getItemById(id))
  .subscribe((item) => {
    this.item = item;
  });
18
Oleksiy Kononenko

Tout devient beaucoup plus facile lorsque vous utilisez des entités. Lorsque vous les stockez en tant qu'objet, où key est un id d'élément et la valeur est l'élément lui-même. Il existe deux manières de conserver les éléments sous forme de tableau: ne stocker que les identifiants ou les objets complets de l'élément.

en réducteur:

export interface ItemsState {
  loaded: boolean;
  loading: boolean;
  items: { [key: string]: Item };
  itemIds: any[];
}

const initialState: ItemsState = {
  loaded: true,
  loading: false,
  items: {
    0: {
      foo: 'bar'
    },
    1: {
      bar: 'foo'
    }
  },
  itemIds: [0, 1]
}

dans les sélecteurs:

export const getItems = (state: ItemsState) => state.items;

export const getItemById = (id) => createSelector(
  getItems 
  (items) => items[id]
);

en conteneur (composant):

constructor(
  private store: Store,
  private route: ActivatedRoute
) {}

getItemOnInit(): void {
  // or any other way to retrieve id from route
  const id = this.route.snapshot.params.id;
  this.store.pipe(select(getItemById(id)));
}
4
Maksym Shevchenko

Sur la base des données disponibles dans le magasin:

export const selectUser = (state: AppState) => state.selectedUser;
export const selectAllBooks = (state: AppState) => state.allBooks;

export const selectVisibleBooks = createSelector(
  selectUser,
  selectAllBooks,
  (selectedUser: User, allBooks: Books[]) => {
    if (selectedUser && allBooks) {
      return allBooks.filter((book: Book) => book.userId === selectedUser.id);
    } else {
          return allBooks;
    }
   }
);

Données non disponibles dans le magasin:

Pour sélectionner un élément d'état basé sur des données non disponibles dans le magasin, vous pouvez passer props à la fonction de sélection. Ces accessoires passent par chaque sélecteur et par la fonction du projecteur. Pour ce faire, nous devons spécifier ces accessoires lorsque nous utilisons le sélecteur dans notre composant.

Par exemple, si nous avons un compteur et que nous voulons multiplier sa valeur, nous pouvons ajouter le facteur multiply en tant que prop:

Le dernier argument d'un sélecteur ou d'un projecteur est l'argument props. Pour notre exemple, il ressemble à ceci:

export const getCount = createSelector(
  getCounterValue,
  (counter, props) => counter * props.multiply
);

À l'intérieur du composant, nous pouvons définir les accessoires:

ngOnInit() {
  this.counter = this.store.pipe(select(fromRoot.getCount, { multiply: 2 }))
}

Hers est la Documentation .

0
Rahmathullah M