0.5.6 • Published 5 years ago
flux-payload-action v0.5.6
Flux Payload Action
FPA is an implementation of flux action, which is really easy to understand and use.
In FPA, there's type and payload properties only, no error, no meta, which avoid the complexity of overload and corner cases.
And by design, FPA supports the following attributes:
- Type-safe with any string type.
- Compatible to Flux Standard Action (FSA).
interface Fpa<TP> {
type: string;
payload: TP;
}Read A rethink of Type-safe Actions (Confluence Page) for more information about the design.
Usage
import { ActionCreator } from "flux-payload-action";
type AnyAction = { type: string }; // maybe import from 'redux'
const ns = "sample-app-module";
// firstly, create an action creator by type name and a specific payload type,
const actionCreator = ActionCreator<number>(`${ns}/balabala`);
// you can create action instance by the 'create' method,
const action = actionCreator(1.1); // Fpa<number>
// and use type guard in reducer,
const reducer = (state: number = 0, action: AnyAction): number => {
// move switch-case style to if-else style
if (actionCreator.match(action)) {
// Type guards: action is Fpa<number>
return action.payload; // number
}
// default branch
return state;
}
// actually, you can narrow the type everywhere you need,
let action: AnyAction;
if (actionCreator.match(action)) {
// action is Fpa<number>
// ...
}Migration Guide
typesafe-actions
For action creating,
// For single action,
// from typesafe-actions style
const action = createStandardAction("T")<T>();
// to flux-payload-action style
const action = ActionCreator<T>("T");
// For async action group
// from typesafe-actions style
const actions = createAsyncAction("T1", "T2", "T3")<T1, T2, T3>();
// to flux-payload-action style
const actions = AsyncGroupCreator<T1, T2, T3>("T");For usage in reducer,
let action1; // Assume there're several action creators
let action2; // ...etc
// from typesafe-actions style
type ActionTypes = ActionType<typeof action1 | typeof action2>;
const reducer = (state, action: ActionTypes) => {
switch (action.type) {
case getType(action1): {
// Type guards for action1
return f1(state, action);
}
case getType(action2): {
// Type guards for action2
return f2(state, action);
}
default: {
return state;
}
}
}
// to flux-payload-action style
const reducer = (state, action: { type: string }) => {
if (action1.match(action)) {
// Type guards for action1
return f1(state, action);
}
if (action2.match(action)) {
// Type guards for action2
return f2(state, action);
}
return state;
}For usage in saga,
let actionCreator; // Assume there's an action creator
// from typesafe-actions style
const action: ActionType<typeof actionCreator> = yield take(getType(actionCreator));
// to flux-payload-action style
const action: ReturnType<typeof actionCreator> = yield take(actionCreator.match);
// from typesafe-actions style
takeLatest(getType(actionCreator), handler);
// to flux-payload-action style
takeLatest(actionCreator.match, handler);