Sigi framework document
Introduction
Basic
ConceptActionDispatcher & ActionsCreatorEffectsDependencies Injection
Recipes
FAQ
基本概念
深入
常见问题

Action

Sigi EffectModule was implemented by State object under the hood. State object is very similar with redux Store object. It Dispatch actions to reducers and effects, and receive actions from Dispatcher and Effect.

In sigi application, you will never need to create an Action by hand, so we do not expose the Dispatch function. In replacement, there are two ways to dispatch action:

  • call methods on Dispatcher
  • emit actions in Effect

Dispatcher & ActionsCreator

Dispatcher is a high level abstraction for ActionsCreator with well defined type information.

Every method in EffectModule class decorated by Reducer, ImmerReducer, Effect , DefineAction Decorators match one property with the same name in ActionsCreator in EffectModule class, and match one property with the same name in Dispatcher in Component. The ActionsCreator in EffectModule class is used for emit action in Effect, and the Dispatcher in Component is used for Dispatch actions to State.

Dispatch props created by Redux-Actions

You may have used Redux-Actions in Redux application. ActionsCreator in sigi is very similar with ActionsCreator in Redux-Actions.And there are few advantages for create ActionsCreator using Redux-Actions:

  • Avoid Magic string
  • Provide type information
  • Reduce boilerplate codes
// raw dispatcher
connect(mapStateToProps, (dispatch) => bindActionCreators({
addCount: (count: number) => dispatch({ // losing type information here
type: 'ADD_COUNT',
payload: count,
}),
}, dispatch))
// reducer
export const reducer = (state, action) => { // losing type information here
switch action.type:
case: 'ADD_COUNT':
return { ...state, count: state.count + payload }
default:
return { count: 0 }
}
const ADD_COUNT = createAction<number>("ADD_COUNT");
interface DispatchProps {
addOne: typeof ADD_COUNT;
}
interface StateProps {
count: number;
}
// react actions dispatcher
connect(mapStateToProps, (dispatch) =>
bindActionCreators(
{
addCount: ADD_COUNT,
} as DispatchProps,
dispatch
)
);
// reducer
export const reducer = handleActions(
{
[`${ADD_COUNT}`]: (state: StateProps, { payload }: Action<number>) => {
return { ...state, count: state.count + payload };
},
},
{ count: 0 }
);

The Sigi way

Definition

import { Module, EffectModule, Reducer } from "@sigi/core";
interface State {
count: number;
}
@Module("SomeNamespace")
class SomeModule extends EffectModule<State> {
defaultState = {
count: 0,
};
@Reducer()
add(state: State, count: number) {
return { ...state, count: state.count + count };
}
}

As you can see above, in the definition part of a sigi app, there is no magic action string, no redundant boilerplate 🤯.

Usage

For react APP, we provide two hooks that let you refer actions defined in effect modules. both of them receive a EffectModule class and produce a dispatcher referred to this module.

useModule and useDispatchers

// use module
import { useDispatchers, useModule } from "@sigi/react";
const SomeComponent = () => {
// note: we don't need to worry about the types of dispatcher.
// Sigi's type system will ensure all defined actions/effects are 100% accurate referred in dispatcher
const [state, dispatcher] = useModule(SomeModule);
// or, if you don't care about the state changes.
// const dispatcher = useDispatchers(SomeModule);
const onClickAdd = useCallback(() => {
// ts will perform typecheck in the payload part
// and you can also perform **Jump to definition** in code editor
dispatcher.add(1);
// ts type error
// dispatch.add('string value')
}, [dispatcher]);
return (
<div>
<button onClick={onClickAdd}>add 1</button>
<span>count: {state.count}</span>
</div>
);
};