Objective Redux

Redux made better, objectively.

StateController

abstract class StateController<State> extends Controller

Creates and manages a slice of Redux state.

Template Parameters

<State>
The interface to which the slice of state will adhere.

Examples

JavaScript
class SwitchStateController extends StateController {
  constructor() {
    super({ isOn: false });
  }

  public static getName() {
    return 'switch';
  }

  action = this.createReducingAction(
    (state, payload) => ({
      ...state,
      ...payload,
    })
  ).withAddressableName('MY_ACTION');
}

const objectiveStore = new ObjectiveStore();
const controller = SwitchStateController.getInstance(objectiveStore);
controller.action({ isOn: true });
const slice = controller.getStateSlice();

initialState

protected initialState: State

The initial value of the state slice.

objectiveStore

protected objectiveStore: ObjectiveStore|null

The ReduxController to which the controller belongs.

reducerMap

protected reducerMap: ReducerMap<State, any>

A map of the reducer action names to the data mutation functions.

reset

public reset: ActionExtendFn<void>

Fires an action that resets the state back to the controller's initial state.

constructor

protected constructor(initialState: State): StateController

Registers the controller, sets up the reducer, and sets the initial state.
WARNING: While the constructor can be called directly, controllers are meant to be initialized with the [[getInstance]] method. Creating instances directly can lead to having more than one instance at a time, which may have adverse affects on the application.

Parameters

initialState: State
The initial value of the state slice in Redux.

Returns

StateController
An instance of the controller.

createActionName

protected createActionName(name: string|null = null): string

Generates a unique, default action name.

Parameters

name: string|null = null
The name of the action or null to generate a unique, default action name.

Returns

string
An action name.

createReducingAction

protected createReducingAction<Payload>(fn: ReducerFn<State, Payload>): ActionExtendFn<Payload>

Registers a data mutator as part of the slice's reducer and returns the action for calling it.

Template Parameters

<Payload>
The interface to which the payload of the action will adhere. If the type is void, no payload
will be accepted. Defaults to void when the template is not provided and the payload type is not specified.

Parameters

fn: ReducerFn<State, Payload>
The mutating function to add to the reducer.
The function should be in the form: ```. (state, payload?) => state ```.

Returns

ActionExtendFn
The action producing function for calling the mutating function.
This action producing function also has a `withAddressableName` function that can be called to change the action name. For example: `myAction.withAddressableName('MY_ACTION_NAME');`.

getStateSlice

public getStateSlice(): State

Gets the current value for this slice of the Redux state.

Returns

State
The current slice of the state related to this controller.

reducer

public reducer(state: State = this.initialState, action: Action<any>|null = null): State

The reducer, which handles mutations to the state slice.

Parameters

state: State = this.initialState
The current state of the state slice.

action: Action<any>|null = null
The action being performed on the state.

Returns

State
The new state resulting from the action.

getInstance

public static getInstance<T>(this: Controller|ModelConstructor<T>, objectiveStore: ObjectiveStore): T

Gets an instance of the class, creating one if it does not yet exist.
This should be used as the method of instantiating controllers.

Template Parameters

<T>
The controller type. Will be inferred from the class instance and does not need to be provided.

Parameters

this: Controller|ModelConstructor<T>
Implicit "this" for internal use. When calling, this parameter should be ignored/skipped.

objectiveStore: ObjectiveStore
An instance of the ObjectiveStore from which to get the controller.

Returns

T
An instance of the controller.

Examples

const instance = MyController.getInstance(objectiveStore);

getName

public static getName(): string

Gets the unique name of the controller. By default, the name of the class.
The name of the controller should be globally unique for all Objective Redux controllers in the application.

Returns

string
The name of the state slice.

getNamespace

public static getNamespace(): string|null

Creates groupings of controllers and state slices. This helps prevent naming collisions, because names only need to be unique within a namespace.
In addition, for StateControllers, the slice of state in the store is also saved into an object of the namespace name. Note that falsy values like null and '' will evaluate to the same empty namespace.

Returns

string|null
Null if the state is not namespaced.

Examples

// For StateControllers, the namespace also groups slices in the store.

class MyFirstController extends StateController {
  // ...

  static getName() {
    return 'MY_FIRST_CONTROLLER';
  }

  static getNamespace() {
    return 'MY_NAMESPACE';
  }

  // ...
}

class MySecondController extends StateController {
  // ...

  static getName() {
    return 'MY_SECOND_CONTROLLER';
  }

  static getNamespace() {
    return 'MY_NAMESPACE';
  }

  // ...
}

// Creates a state of the form:
//
// {
//   MY_NAMESPACE: {
//     MY_FIRST_CONTROLLER: {
//       // ...
//     },
//     MY_SECOND_CONTROLLER: {
//       // ...
//     },
//   },
// }

initializeOnExternalAction

public static initializeOnExternalAction<T>(this: T): void

Allows the controller to be lazy loaded by actions triggered outside of Objective Redux.
In order for calls to be routed to the controller without using the controller directly, and thus to lazy-load without using the controller directly, this needs to be used in conjunction with the method [[withAddressableName]].

Template Parameters

<T>

Parameters

this: T
Implicit "this" parameter, which does not need to be supplied.

Returns

void

Examples

class MyController extends StateController<MySliceType> {
  public static getName() {
    return 'MY_CONTROLLER';
  }

  action = this.createReducingAction(
    (state, payload) => ({
      ...state,
      ...payload,
    })
  ).withAddressableName('MY_ACTION'); // <-- also required
}

MyController.initializeOnExternalAction();

export MyController;

// ... elsewhere ...

// By firing this action, the controller will now be instantiated (if it hasn't been).
const myAction = createAction(getActionNameForController('MY_CONTROLLER', 'MY_ACTION'));
objectiveStore.dispatch(myAction);

removeInstance

public static removeInstance<T>(this: Controller|ModelConstructor<T>, objectiveStore: ObjectiveStore): void

Removes the instance of the controller from the store. This will unregister reducers any stop saga associated with the controller.

Template Parameters

<T>

Parameters

this: Controller|ModelConstructor<T>
Implicit "this" for internal use. When calling, this parameter should be ignored/skipped.

objectiveStore: ObjectiveStore
An instance of the ObjectiveStore from which to get the controller.

Returns

void

Examples

MyController.removeInstance(objectiveStore);