Handle your state with typed actions.
- Async dispatches
- Typed actions (to request a change of state)
- Stores are classes
- Made for DI Containers via interface
- Listen for store changes
Define an action:
export class LoginAction {
constructor(public userName: string, public password: string) {}
}
Define a store:
import { Store, handle } from "fw-state";
// the file that the above action is defined in...
import { LoginAction } from "./actions";
export class MyStore1 extends Store<{ loggedIn: boolean }> {
defaultState() {
return {
loggedIn: false,
};
}
@handle(LoginAction)
private async handleLogin(action: LoginAction) {
// you can await network calls here.. or perform other logic
// if you want too, throw
if (someError) {
throw new Error("Could not log in");
}
// when you are satisfied, you can update the state of this store..
this.setState(state => ({
...state,
loggedIn: true,
}));
}
}
Before you can dispatch to stores, you must set them up.
import { setupStores } from "fw-state";
setupStores(containerInstance,
MyStore1,
MyStore2,
);
Now we can dispatch:
import { dispatch } from "fw-state";
import { LoginAction } from "./actions";
await dispatch(new LoginAction("user", "password"));
You can await
your dispatch (if you want) or just fire and forget..
Dispatching will call all of the handlers on every store that handles it.
Example:
// in your actions
export class LogoutAction {}
// in a store:
// ....
@handle(LogoutAction)
private handleLogout() {
this.setState(_ => this.defaultState());
}
// ....
You can imagine that if you have a lot of different stores containing data, dispatching one action to reset every stores' state is ideal.
const myStore1 = containerInstance.get(MyStore1);
const { loggedIn } = myStore1.state;
console.log(loggedIn ? "Hi!!" : "Please Log In");
If you need to, you can manually listen to changes with:
const myStore1 = containerInstance.get(MyStore1);
const disposer = myStore1.onStateChanged(() => {
// state changed
});
// when you are done:
disposer.dispose();