Entities Props Factory
There are two built-in entities props included in Elf - withEntities
and UIEntities
. In addition to that, we can create our own entities props for our stores.
Let's say we have a products page with a shopping cart. As well as managing a store for products, we must also maintain a shopping cart. We can create a new Store
for our cart
or a cart
entity props in the same products
store.
First, let's create the products
store:
import { createStore } from '@ngneat/elf';
import { withEntities } from '@ngneat/elf-entities';
interface Product {
id: number;
title: string;
price: number;
}
export const productsStore = createStore(
{ name: 'products' },
withEntities<Product>()
);
Now we can add a cart
entities props to the same store
:
import { createStore } from '@ngneat/elf';
import { withEntities, entitiesPropsFactory } from '@ngneat/elf-entities';
const { cartEntitiesRef, withCartEntities } = entitiesPropsFactory('cart');
interface Product {
id: number;
title: string;
price: number;
}
interface CartItem {
id: Product['id'];
quantity: number;
}
export const productsStore = createStore(
{ name: 'products' },
withEntities<Product>(),
withCartEntities<CartItem>()
);
The entitiesPropsFactory
function takes the name of the feature
and returns entitiesRef
and entitiesProps
we can use in our store.
In the above example, our final state
shape will be:
{
entities: Record<number, Product>;
ids: number[];
cartEntities: Record<number, CartItem>;
cartIds: number[];
}
We can pass the cartEntitiesRef
to each one of the built-in queries and mutations:
import { upsertEntitiesById } from '@ngneat/elf-entities';
export function updateCart(id: Product['id']) {
productsStore.update(
upsertEntitiesById(id, {
updater: (e) => ({ ...e, quantity: e.quantity + 1 }),
creator: (id) => ({ id, quantity: 1 }),
ref: cartEntitiesRef,
})
);
}
One more use case for custom entities props is when we work with a normalized state. For example, we might have a movies
page, with actors
and genres
:
interface Actor {
id: string;
name: string;
}
interface Genre {
id: string;
name: string;
}
interface Movie {
id: string;
title: string;
genres: Array<Genre['id']>;
actors: Array<Actor['id']>;
}
const { actorsEntitiesRef, withActorsEntities } =
entitiesPropsFactory('actors');
const { genresEntitiesRef, withGenresEntities } =
entitiesPropsFactory('genres');
const store = createStore(
{ name: 'movies' },
withEntities<Movie>(),
withGenresEntities<Genre>(),
withActorsEntities<Actor>()
);
store.update(
addEntities({ id: '1', name: 'Nicolas cage' }, { ref: actorsEntitiesRef }),
addEntities({ id: '1', name: 'Action' }, { ref: genresEntitiesRef }),
addEntities({
id: '1',
title: 'Gone in 60 Seconds',
genres: ['1'],
actors: ['1'],
})
);