Le créateur de NGRX Signal Store, Marko Stanimirovic décrit ici NgRx SignalStore : examen approfondi de la gestion de l'état basée sur le signal dans Angular
Explorons l'API du magasin avec des exemples de code. Nous utiliserons un projet avec une liste de produits et de fonctionnalités de filtrage.
import { signalStore } from "@ngrx/signals"; export const ProductStore = signalStore( … );
Comme pour n'importe quel magasin NGRX jusqu'à présent, un état initial peut être fourni, en utilisant la fonction withState qui accepte les littéraux d'objet, les enregistrements ou les fonctions d'usine (pour créer un état initial dynamique) comme entrées.
import { signalStore, withState } from "@ngrx/signals"; const initialProductState: ProductState = { products: [] }; export const ProductStore = signalStore( withState(initialProductState); );
import { signalStore, withComputed, withState } from "@ngrx/signals"; export const ProductStore = signalStore( withState(initialProductState), withComputed(({products}) => ({ averagePrice: computed(() => { const total = products().reduce((acc, p) => acc + p.price, 0); return total / products().length; }) })),
import { signalStore, withComputed, withState, withMethods } from "@ngrx/signals"; export const ProductStore = signalStore( withState(initialProductState), withComputed(({products}) => ({ averagePrice: computed(() => { const total = products().reduce((acc, p) => acc + p.price, 0); return total / products().length; }) })), // CRUD operations withMethods((store, productService = inject(ProductService), ) => ({ loadProducts: () => { const products = toSignal(productService.loadProducts()) patchState(store, { products: products() }) }, addProduct: (product: Product) => { patchState(store, { products: [...store.products(), product] }); }, // ... })),
withMethods & withComputed accède à une fonction d'usine et renvoie un dictionnaire de méthodes et de signaux calculés accessibles en utilisant le magasin. Ils s'exécutent également dans un contexte d'injection, ce qui permet de leur injecter des dépendances.
import { withHooks } from "@ngrx/signals"; export const ProductStore = signalStore( withHooks((store) => ({ onInit() { // Load products when the store is initialized store.loadProducts(); }, })), );
export const ProductStoreWithEntities = signalStore( withEntities<Product>(), // CRUD operations withMethods((store, productService = inject(ProductService), ) => ({ loadProducts: () => { const products = toSignal(productService.loadProducts())(); patchState(store, setAllEntities(products || [])); }, updateProduct: (product: Product) => { productService.updateProduct(product); patchState(store, setEntity(product)); }, })),
Il est possible d'ajouter plusieurs fonctionnalités commençant par « avec » mais elles ne peuvent accéder qu'à ce qui a été défini avant elles.
signalStoreFeature - utilisé pour étendre les fonctionnalités du magasin.
Les magasins peuvent devenir complexes et difficiles à gérer pour les applications des grandes entreprises. Lors de l'écriture de fonctionnalités et de composants pour un projet, plus la répartition est précise et granulaire, plus il est facile de gérer, de maintenir le code et d'écrire des tests pour celui-ci.
Cependant, compte tenu de l'API fournie par SignalStore, le magasin peut devenir difficile à gérer à moins que le code ne soit divisé en conséquence. signalStoreFeature convient pour extraire la fonctionnalité spécifique d'une fonctionnalité (ou d'un composant) dans une fonction testable autonome qui peut potentiellement (et idéalement) être réutilisée dans d'autres magasins.
export const ProductStore = signalStore( // previous defined state and methods // Externalizing filtering options withFilteringOptions(), ); export function withFilteringOptions() { return signalStoreFeature( // Filtering operations withMethods(() => ({ getProductsBetweenPriceRange: (lowPrice: number, highPrice: number, products: Array<Product>, ) => { return products.filter(p => p.price >= lowPrice && p.price <= highPrice); }, getProductsByCategory: (category: string, products: Array<Product>) => { return products.filter(p => p.category === category); }, })), ); }
Maintenant, un exemple de signalStoreFeature qui montre la possibilité de réutiliser signalStoreFeature(s) dans plusieurs magasins.
importer { patchState, signalStoreFeature, withMethods } depuis "@ngrx/signals";
export function withCrudOperations() { return signalStoreFeature( withMethods((store) => ({ load: (crudService: CrudOperations) => crudService.load(), update: (crudableObject: CRUD, crudService: CrudOperations) => { crudService.update(crudableObject); patchState(store, setEntity(crudableObject)); }, }), )); } export interface CrudOperations { load(): void; update(crudableObject: CRUD): void; } // Product & Customer services must extend the same interface. export class ProductService implements CrudOperations { load(): void { console.log('load products'); } update(): void { console.log('update products'); } } export class CustomerService implements CrudOperations { load(): void { console.log('load customers'); } update(): void { console.log('update customers'); } } // and now let’s add this feature in our stores export const ProductStore = signalStore( withCrudOperations(), ); export const CustomerStore = signalStore( withCrudOperations(), );
Étant aussi simple à étendre, il existe déjà un package utilitaire appelé ngrx-toolkit destiné à ajouter des outils utiles aux Signal Stores.
{ provideIn: 'root' } ou dans le tableau fournisseurs d'un composant, d'un service, d'une directive, etc.
Il reste à prouver sa fiabilité pour les applications plus importantes, en particulier lorsqu'il est appliqué en tant que magasin mondial.
Pour l'instant, je pense que c'est un excellent ajout à l'API Signal par défaut, ce qui en fait une bonne option pour gérer :
https://www.stefanos-lignos.dev/posts/ngrx-signals-store
https://www.angulararchitects.io/blog/the-new-ngrx-signal-store-for-angular-2-1-flavors/ (groupe de 4 articles sur le sujet)
https://ngrx.io/guide/signals
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!