Reactables Core API
Reactable
Reactables provide the API for applications and UI components to receive and trigger state updates.
It is a tuple with the first item being an Observable emitting state changes and the second item is a dictionary of action methods for triggering state updates.
Reactables may also expose an optional third item - an observable emitting all the actions the received by the store during state updates. This can be helpful if other reactables also want to subscribe and react to any of those actions.
export type Reactable<T, S = ActionMap> = [Observable<T>, S, Observable<Action<unknown>>?];
export interface ActionMap {
[key: string | number]: (payload?: unknown) => void | ActionMap;
}
RxBuilder
Factory function for building a reactable primitive. Accepts a RxConfig configuration object.
declare const RxBuilder: <T, S extends Cases<T>>(config: RxConfig<T, S>) => Reactable<T, { [K in keyof S]: (payload?: unknown) => void; }>;
RxConfig
Configuration object for creating Reactables.
interface RxConfig <T, S extends Cases<T>>{
initialState: T;
reducers: S;
debug?: boolean;
effects?: Effect<unknown, unknown>[];
sources?: Observable<Action<unknown>>[] | { [key: string]: Observable<unknown> };
}
interface Cases<T> {
[key: string]:
| SingleActionReducer<T, unknown>
| {
reducer: SingleActionReducer<T, unknown>;
effects?: Effect<unknown, unknown>[] | ((payload?: unknown) => ScopedEffects<unknown>);
};
}
type SingleActionReducer<T, S> = (state: T, action: Action<S>) => T;
Property | Description |
---|---|
initialState | Initial state of the Reactable |
reducers | Dictionary of cases for the Reactable to handle. Each case can be a reducer function or a configuration object. RxBuilder will use this to generate Actions, Reducers, and add ScopedEffects . |
debug (optional) | to turn on debugging to console.log all messages received by the store and state changes |
effects (optional) | Array of Effects to be registered to the Reactable |
sources (optional) | Additional Action Observables the Reactable is listening to. Can be an array or a dictionary where key is the action type and value is the Observable emitting the payload |
ofTypes
Function that accepts an array of action types (string
) and returns an OperatorFunction
that will filter for those Action
s.
export declare const ofTypes: (types: string[]) => OperatorFunction<Action<unknown>, Action<unknown>>;
storeValue
Decorator function used store the state value in a ReplaySubject
instead of an Observable
so subsequent subscriptions can access the latest stored value.
Also add’s a destroy
action method to be called to teardown any Reactable decorated with storeValue
.
interface DestroyAction {
destroy: () => void;
}
declare const storeValue: <T, S>(reactable: Reactable<T, S>) => Reactable<T, S & DestroyAction>;
Other Interfaces
Effect
Effects are expressed as RxJS Operator Functions. They pipe the dispatcher$
stream and run side effects on incoming Actions
.
type Effect<T, S> = OperatorFunction<Action<T>, Action<S>>;
ScopedEffects
Scoped Effects are declared when defining reducers in RxConfig. They are dynamically created stream(s) scoped to an Action type
& key
combination.
interface ScopedEffects<T> {
key?: string;
effects: Effect<T, unknown>[];
}
Property | Description |
---|---|
key (optional) | key to be combined with the Action type to generate a unique signature for the effect stream(s). Example: An id for the entity the action is being performed on. |
effects | Array of Effects scoped to the Action type & key |
Action
interface Action<T = undefined> {
type: string;
payload?: T;
scopedEffects?: ScopedEffects<T>;
}
Property | Description |
---|---|
type | type of Action being dispatched |
payload (optional) | payload associated with Action |
scopedEffects (optional) | See ScopedEffects |
Reducer
From the Redux Docs:
Reducers are functions that take the current state and an action as arguments, and return a new state result
type Reducer<T> = (state?: T, action?: Action<unknown>) => T;