Now we can wire up some handlers in our store so that we can do things when Actions are dispatched.
-
Handlers are not called directly by your code; instead, they are invoked when an Action of a matching Type
is dispatched.
-
Each handler is passed 2 arguments:
- A
StateContext<T>
, which provides some operations to interact with state at the time the handler is executed. - The dispatched Action that triggered it.
import { Store, StateContext, StoreConfig } from '@animus-bi/Bixe';
import * as TodosActions from './actions';
import { TodoState } from './state';
const createTodo = (ctx: StateContext<TodoState>, action: TodosActions.CreateTodo) => {
const { list, hash } = ctx.getState();
list.push(action.payload);
hash[action.payload.task] = action.payload;
return ctx.patchState({ list, hash });
}
export TodoStore = Store.Create<TodoState>({
});
-
In order that the createTodo
function is called when the Action is dispatched, we must add it to our store's StateConfig so that our Action type
is the key name for the handler.
-
Note: you are not calling the handler in the config, but rather, you're passing a reference to the handler. To avoid any lexical problems, use .bind(this)
import { Store, StateContext, StoreConfig } from '@animus-bi/Bixe';
import * as TodosActions from './actions';
import { TodoState } from './state';
const createTodo = (ctx: StateContext<TodoState>, action: TodosActions.CreateTodo) => {
const { list, hash } = ctx.getState();
list.push(action.payload);
hash[action.payload.task] = action.payload;
return ctx.patchState({ list, hash });
}
export TodoStore = Store.Create<TodoState>({
name: TodosActions.Intent,
initialState: new TodoState(),
handlers: {
[TodosActions.CreateTodo.Type]: createTodo.bind(this)
}
});
-
You may also attach multiple handlers to a single dispatched action:
import { Store, StateContext, StoreConfig } from '@animus-bi/Bixe';
import * as TodosActions from './actions';
import { TodoState } from './state';
const preCreateTodo = (ctx: StateContext<TodoState>, action: TodosActions.CreateTodo) => {
console.log('intend to create a todo');
}
const createTodo = (ctx: StateContext<TodoState>, action: TodosActions.CreateTodo) => {
const { list, hash } = ctx.getState();
list.push(action.payload);
hash[action.payload.task] = action.payload;
return ctx.patchState({ list, hash });
}
export TodoStore = Store.Create<TodoState>({
name: TodosActions.Intent,
initialState: new TodoState(),
handlers: {
[TodosActions.CreateTodo.Type]: [
preCreateTodo.bind(this)
createTodo.bind(this)
]
}
});
-
You should NOT list the same key twice in a store's action handler config (this is standard js stuff).
- You could do this, but the last one will probably win, and the other may not fire at all. Just use the one key with an array of handlers
import { Store, StateContext, StoreConfig } from '@animus-bi/Bixe';
import * as TodosActions from './actions';
import { TodoState } from './state';
const preCreateTodo = (ctx: StateContext<TodoState>, action: TodosActions.CreateTodo) => {
console.log('intend to create a todo');
}
const createTodo = (ctx: StateContext<TodoState>, action: TodosActions.CreateTodo) => {
const { list, hash } = ctx.getState();
list.push(action.payload);
hash[action.payload.task] = action.payload;
return ctx.patchState({ list, hash });
}
export TodoStore = Store.Create<TodoState>({
name: TodosActions.Intent,
initialState: new TodoState(),
handlers: {
[TodosActions.CreateTodo.Type]: preCreateTodo.bind(this),
[TodosActions.CreateTodo.Type]: createTodo.bind(this)
}
});