Sunday, April 25, 2021
Ngrx Selectors
I look at selectors in Ngrx as queries on the data store. They are the method of getting data from the store to the components in the shape of an observable.
this.dataobservable = this.store.select(selectorfunction);
}
The thing to remember is that store.select passes the entire state to the selector function. Lets lay out a state structure, and see how selectors would work.
export const getJobState = createFeatureSelector<JobClientState>(jobFeatureKey);
Remember, this.store.select(selector) passes the entire state tree to the selector. If this wasn't a feature state, the first selector would look like this
export const getJobState = createSelector((state: AppState) => state=> state.Job)
where "Job" is jobFeatureKey.
Where do I put this? The file structure of where you place your selectors is important. In this instance, the data from one entity will be needed by another to assemble the data, and if you aren't careful you can create a circular dependency between files. The solution is to build a tree. Create a file for each Entity or state property. Then create a file where the different entities or properties are combined. A tree.
Let's start with the jobs state selectors. This is an Entity state, which exposes selectors for the data. Entity state looks like this:
{ ids: string[], entities: Dictionary<T>}
Dictionary is an object. You access the data with the id, and ids is an array of id. The id is derived from the object itself; you need a unique id for each entity.
entity[id]
Entity selectors are generated by the schematic, and look like this
export const {
selectIds,
selectEntities,
selectAll,
selectTotal,
} = adapter.getSelectors();
With the feature selector, and the Entity selectors, we can then combine selectors and drill down to the data we want. So for the job state:
export const getJobs = createSelector(getJobState, (state) => state.jobs);
export const getJobIds = createSelector(getJobs, jobs.selectIds);
export const getJobEntities = createSelector(getJobs, jobs.selectEntities);
Each of the JobClientState properties that are Entity State will have the same type of selectors.
What about the Query and Primary states? Query is for the list of jobs to be displayed for the user to select. JobPrimary is the selected job, and has a similar selector.
export const getJobQuery = createSelector(getJobState, (state) => state.jobquery);
When a job is selected, the user navigates to an edit or view url, with the id. The router state is subscribed to, and the primaryjob state is set with that id. The view then uses this selector to get the selected job
export const getJobPrimary = createSelector( getJobState, (state) => state.jobprimary)
export const JobPrimaryEntity = createSelector( getJobPrimary, getJobEntities, (primary, entities) => entities[primary]);
Subscribe to Posts [Atom]