Use values from store state in main.ts


#1

I’m using aurelia store and would like to setRoot based on values in the store in main.ts, eg:

aurelia.setRoot(state.isAuthenticated ? 'app' : 'auth');

How can I access the state in main.ts? Or should I not use the store for this?


#2

During app bootstrapping, you’re setting up the store plugin with an initialState, which is likely a local const. So you don’t really need the state subscription as you can re-use this. Anyways for whatever reason you might be tempted to do a read from the store, without having to subscribe then you can do it the following way (please try to avoid it if possible):

// state.ts

export interface State {
  isAuthenticated: boolean;
}

// main.ts
import { Store } from "aurelia-store";
import { State } from "./state";
...

export function configure(aurelia: Aurelia): void {
  aurelia.use
    .standardConfiguration()
    .developmentLogging();

  aurelia.start().then(() => {
    const store = aurelia.container.get(Store) as Store<State>;

   // try to avoid the following as much as possible
   const currentState = (store as any)._state.getValue();
    aurelia.setRoot(currentState.isAuthenticated ? 'app' : 'auth');
  });
}

#3

Thanks, that got me on the right track. I went with:

aurelia.use.plugin('aurelia-store', { initialState });
await aurelia.start();
const store: Store<State> = aurelia.container.get(Store);
let root = '';
store.state.subscribe(async x => {
  if (root != x.aureliaRoot) {
    root = x.aureliaRoot;
    await aurelia.setRoot(root);
  }
});

My store actions set aureliaRoot to either ‘app’ or ‘auth’ as appropriate.

The reason I use subscribe here is because I followed the documentation and created a “rehydrateFromLocalStorage” action, as the isAuthenticated is set based on having an unexpired token in localstorage. I’m in two minds now, because maybe it would be preferable to get the localstorage values when creating the initialstate. Should I prefer one approach over the other?


#4

Thinking about this some more, not sure it really makes sense to have the root in the store.


#5

It really depends on your use-case, but nevertheless we can pretty much say you are only interested in the second emitted value right? Just add .pipe(skip(1), take(1)).subscribe... that way the subscription will automatically complete afterwards without having to think about disposal.


#6

I’m now trying to dispatch an action in main.ts, but the state is null when debugging the action. Is this not supported? When is the store “ready”? Where should you put “initializing” actions?


#7

As soon as the DI has inited the Store, so typically after its first inject, so typically app.ts. You can use aurelia.container.get(Store) though already inside main.ts to require it manually


#8

Thanks. Learnt a bit about how DI works. I am using the approach to registering actions outlined here. I was getting null state in the action because the action was being registered before the store was initialized by aurelia DI (I was importing the action into main.ts). Fix was to not register the action in the action file, as the author does, but to register after aurelia start. Thanks for your help.