I want to do this:
export const selectPlacesForCurrentCustomer = createSelector(
selectAllPlaces,
selectedCustomerId,
(places: Place, customer_id: string) => places.filter((place) => place.customer === customer_id)
)
However when I do this, I get this error:
Argument of type 'MemoizedSelector<State, string,
DefaultProjectorFn>' is not assignable to parameter of type
'Selector<State, string>'.
Here is a simplified version of my application that reproduces the issue.
https://stackblitz.com/edit/angular-10-ngrx-issue?file=src/app/reducers/index.ts
Here's a screenshot of my state. I want to combine these two things:
**************** Background ******************
I have two separate feature stores. Each store uses NGRX/Entity.
- Places
- Customer
I would like to create a selector that pulls data from both. Here's a simplified interface for both models:
export interface Place {
_id: string;
customer: string;
...
}
export interface Customer {
_id: string;
}
Customer Module
The Customer Feature has multiple stores. I import this feature into my customer module like so:
StoreModule.forFeature(fromCustomer.customersFeatureKey, fromCustomer.reducers)
The customer feature state looks like this:
export interface CustomerState {
[fromCustomers.customerFeatureKey]: fromCustomers.State; //I'm want pull data from here!!
[fromPaymentMethods.paymentmethodFeatureKey]: fromPaymentMethods.State;
[fromInvoices.invoiceFeatureKey]: fromInvoices.State;
[fromSubscriptions.subscriptionFeatureKey]: fromSubscriptions.State;
}
// This is what I pass to the `forFeature` method in my customer module.
export function reducers(state: CustomerState | undefined, action: Action) {
return combineReducers({
[fromCustomers.customerFeatureKey]: fromCustomers.reducer,
[fromPaymentMethods.paymentmethodFeatureKey]: fromPaymentMethods.reducer,
[fromInvoices.invoiceFeatureKey]: fromInvoices.reducer,
[fromSubscriptions.subscriptionFeatureKey]: fromSubscriptions.reducer
})(state, action);
}
If we examine the fromCustomers.State
state, this is what that looks like:
export interface State extends EntityState<Customer> {
selectedCustomerId: string | null; // --> This is the first piece of data I'm trying to select.
loaded: boolean;
loading: boolean;
processing: boolean;
}
export const adapter: EntityAdapter<Customer> = createEntityAdapter<Customer>({
selectId: customer => customer._id,
sortComparer: false
});
export const initialState: State = adapter.getInitialState({
selectedCustomerId: null,
loaded: false,
loading: false,
processing: false
});
...
As we can see above, this were I finally setup the EntityAdapter. The important piece of data that I'm trying to select from this feature is: selectedCustomerId
.
I have a selector in this feature that looks like this:
export const selectedCustomerId = createSelector(
selectCustomersEntitiesState,
(state) => state.selectedCustomerId
)
Place Module
Now that we have customer module summarized, let's move on to the Place Feature.
Similar to the customer module, I'm importing this into the place module file.
This is what my Place State looks like:
export interface PlaceState {
[fromPlaces.placeFeatureKey]: fromPlaces.State;
//[fromSearch.searchFeatureKey]: fromSearch.State; // This is where you should add search for assignments
}
export interface State extends fromRoot.State {
[placesFeatureKey]: PlaceState;
}
// This is what I pass to the `forFeature` method in my place module.
export function reducers(state: PlaceState | undefined, action: Action) {
return combineReducers({
[fromPlaces.placeFeatureKey]: fromPlaces.reducer,
})(state, action);
}
If we dive down into the [fromPlaces.placeFeatureKey]
you'll see where I'm setting up the EntityAdapter for the place model.
export interface State extends EntityState<Place> {
selectedPlaceId: string | null;
loaded: boolean;
loading: boolean;
processing: boolean;
}
export const adapter: EntityAdapter<Place> = createEntityAdapter<Place>({
selectId: place => place._id,
sortComparer: false
});
export const initialState: State = adapter.getInitialState({
selectedPlaceId: null,
loaded: false,
loading: false,
processing: false
});
I have a selector for all places:
export const {
selectIds: selectPlaceIds,
selectEntities: selectPlaceEntities,
selectAll: selectAllPlaces, // --> This second thing I'm trying to select.
selectTotal: selectTotalPlaces,
} = fromPlaces.adapter.getSelectors(selectPlacesEntitiesState);
The selector from place feature that I'm interested in is selectAllPlaces
.
I hope you're still with me. **Now that I've set up the background, I would like to explain what I what hope to do, but can't figure out how.
********** I want to do this: **********
export const selectPlacesForCurrentCustomer = createSelector(
selectAllPlaces,
selectedCustomerId,
(places: Place, customer_id: string) => places.filter((place) => place.customer === customer_id)
)
However when I do this, I get this error:
Argument of type 'MemoizedSelector<State, string,
DefaultProjectorFn>' is not assignable to parameter of type
'Selector<State, string>'.
question from:
https://stackoverflow.com/questions/66058838/how-do-i-create-a-ngrx-selector-that-combines-data-from-two-different-feature-mo