Today we can reuse logic for avoiding Store injection with @ngxs-labs/dispatch-decorator. This package simplifies the dispatching process, you shouldn’t care about
Store service injection as we provide more declarative way to dispatch events out of the box. It also enables a very clean implementation of an NGXS Facade. Read on to find out more…
Dispatch from component
Firstly you have to create a state:
Register this state in
NgxsModule and import this state and actions in your component:
@Dispatch() is a decorator that allows you to decorate methods and properties of your components, basically arrow functions are properties.
Unfortunately, we still have to write a lot of business logic right in the components. Perhaps we lack additional abstraction. In many ways, we would like to have an additional layer of interaction with our states, so that we do not need to mix everything up in the components.
That is, the problem lies in the fact that you cannot immediately distinguish what actions are needed for what, what state they belong to. When writing a lot of NGXS code — as many enterprises do — developers quickly accumulate large collections of actions and selectors classes. These classes are used to respectively dispatch requests to- and query from- the NGXS Store. Unfortunately — with this standard approach — each view component is required to know about many NGXS artifacts and about NGXS state management.
Using a Facade — to wrap and blackbox NGXS— simplifies accessing and modifying your NGXS state by masking internal all interactions with the
In many ways, we would like to encapsulate interactions with our states and make it clearer. And we have such an opportunity
The facade pattern is a software-design pattern commonly used in object-oriented programming. Analogous to a facade in architecture, a facade is an object that serves as a front-facing interface masking more complex underlying or structural code. A facade can:
- improve the readability and usability of a software library by masking interaction with more complex components behind a single (and often simplified) API;
- provide a context-specific interface to more generic functionality (complete with context-specific input validation);
- serve as a launching point for a broader refactor of monolithic or tightly-coupled systems in favor of more loosely-coupled code.
While this seems like a rather trivial change (and an extra layer), the Facade has a huge positive impact of developer productivity and yields significantly less complexity in the view layers. Let’s see what our facade looks like:
The facade has an explicit public API that exposes:
- public observables (e.g.
heroes.data$) to private queries for Store state.
- public methods (e.g.
addHero(), deleteHero(), loadAll()) that hide internals of Store usages.
loadAll()demonstrates that the async call can be done here outside the State class (before any action gets dispatched) if you prefer to avoid putting async code in your State.
Thus, we can easily bring business logic to specialized services, and state classes will only deal with state writing in the repository. Now we no longer smear the functionality of the components, but simply interact with the facade, which can be easily refactored or replaced.