State management for larger apps


#1

I have a larger application (Aurelia, Firebase, Typescript) and as a learning path, I would like to start using aurelia’s state management, but I still struggle with some basic.

If I have a multiple Services (CustomerService, SchoolService, ParentService, … ) and each service does it’s own data manipulation (crud, etc.), how do I go about creating a store? Should the store look like this:

 export const initialState = { 
	customers: [],
	schools: [],
	parents: [],
    ...
 }

and contain all data from the app?

What is the good practice in creating action classes for larger apps?

I’ve looked through the examples (https://github.com/zewa666/aurelia-store-examples), but they all seem to be fairly simple ones.


#2

I think there is no silver bullet to this. Recently I’ve talked with few people about how Vuex approaches this with Modules, but that pumps up the whole system with yet another concept.

Looking at redux and the likes, you’d typically design your app to work with one store. So everything that is handled, comes into one state. The reason for one state has been repeated over and over again, with values like Single-source-of-truth, easier history navigation etc.

So yes, in your case I’d stuff all in the state, as depicted above by you.
Now I agree that this might become a bit unhandy, as lets say the CustomerService is only interested in the customer prop but doesn’t care about the others. So to avoid that you can simply pluck your streamed state to exactly the part you’re interested in.

With the @connectTo decorator that would look like the following:

@connectTo({
  selector: (store) => store.state.pluck("customers")
})

if you’re not using the decorator then like this:

class CustomerService {
  ...
  bind() {
    this.subscription = this.store.state.pluck("customers").subscribe(
      (customerSlice) => this.customers = customerSlice
    );
  }
}

So this would already help you with only seeing the slice of the state you’re interested at.
When it comes to heavier work on top of a large state, you can get some ideas from flattening/normalizing your state.


To sum up … Aurelia-Store uses RxJS, so it uses streams. That means you can take whatever advantage of the vast eco-system of RxJS operators that you like, to create streams or subscriptions in such a way you need.


#3

So the idea is really to keep the state of the whole application in one place. That was the part I struggled to digest. I’ve read more about redux and state management and everything is starting to make a more sense. Thank you for your reply!


#4

Redux can be seen in various ways, but the base concepts they have are really nice patterns and pretty barebone.


#5

I have similar issue but then I still haven’t decided which way to go. I just keep it stupid simple for now, but not sure if it’s the right way without considering performance issue

So, I have one class where it holding my app state

import {Store} from 'aurelia-store'

export class AppStore {
    static inject = [Store];
    
    constructor(store) {
        this.store = store;

       // here is the magic lol
        this.storeSubscriber = this.store.state.subscribe((state) => {
            this.instance = state
        );
    }
    
}

And I inject the AppState class to my components / services

import {AppStore} from './app-store'

export class MyComponent {
    static inject = [AppStore];
    constructor(appStore) {
          this.appStore = appStore;
          // then I can use this.appStore.instance[propName] to get the state
    }
}

@zewa666 could you help with your opinion about my approach?


#6

Your approach is fine to start with. Often you have a service oriented architecture, where your approach fits well in the beginning. In the long run I would personally structure my components to take state slices only via custom attributes which are bound all from the top App component.


#7

What benefits do you see from your personal approach? Performance? Or just a personal preference?


#8

More of a architectural design choice. Here is an old post about a predecessor of the Store plugin http://pragmatic-coder.net/using-a-state-container-with-aurelia/


#9

So all data would get to component only via bound attributes? Does it mean that the main app component would get the data prior to child component and update it accordingly? Do you have an sample app with this aproach? Thank you!


#10

Yep i think its the Services sample from here https://github.com/zewa666/aurelia-store-examples