Skip to main content

Setting up a Reactive State

We're assuming you've already covered the basics here.

In this section, we will be working with an imperative code base to refactor its state management to a reactive setup.

We will set up RxState in the component, initialize the component's local state, and render it in the template.

In addition, we've introduced automated subscription handling, the possibility for imperative interaction over component's input bindings, and a clean separation of concerns.


Implement RxState service

The first step is to introduce a reactive state to our component by using the RxState class. This can be done either through inheritance, which means we extend the state service; or through composition, in which case we inject the service into the constructor and add the service to the component's providers section.

In this case, we will simply extend the service. One distinct feature of this method, which is both its benefit and disadvantage, is that we can directly access the service's API using this (e.g., this.select('prop').)

To this end, we have to extend our class and use the already existing ComponentState interface (see setup.start.component.ts.)


// 1- import RxState
import { RxState } from '@rx-angular/state';

...

// 2- define a component state
interface ComponentState {
refreshInterval: number;
list: DemoBasicsItem[];
listExpanded: boolean;
}

// 3- extend the component, or alternatively, register a local provider and inject it
export class SetupStart extends RxState<ComponentState> implements OnInit, OnDestroy ... {

Since we decided to create a reactive state by extending an existing component, we will need to extend its class definition and call super() in the constructor.

constructor(...) {
super();
}

For the sake of example, we added the state to the same file, but for a more robust architecture, consider having it in a separate file with the .state.ts extension.

Select and display state

The next step is to set up model$, a component property that holds all data we wish to display in the template.

By assigning the model$ to the $ property of the RxState class, we get the full state object as Observable<ComponentState>.

@Component({
selector: 'rxa-setup-solution',
template: `
model$: <pre>{{model$ | async | json}}</pre>
...
`,
...
})
export class SetupReactiveComponentStateContainerComponent extends RxState<ComponentState> {
model$ = this.select();
list$: Observable<DemoBasicsItem[]> = this.select('list')
}

Initialize the state

As RxState is empty and thus lazy at initialization, we can decide if we want to assign initial values to the state and which values these will be. We can initialize the state imperatively by calling set() or by using an observable and the connect() method.

We will use set() as we already have initial values assigned to the initComponentState object's properties.

 constructor(...) {
...
this.set(initComponentState);
}

After we have completed all these steps, we should see the initial state in the template.