reactorx
reactorx copied to clipboard
mv core to https://github.com/querycap/webappkit
Reactorx
React stack based on rxjs
Notice
- Only for TypeScript (checking type in coding over in runtime)
- No any propTypes for runtime checking
- Only support react and it's version must be 16.8+
react hooksis so cool
Packages
@reactorx/core 
This is a redux-like library, and:
-
Declare class
Actor, implementsRedux Action:group: string- classifying actions
name: string- action name
stage?: AsyncStage- mark async stage
STARTED,DONE,FAILED
- mark async stage
get type(): string- computed by
group,nameandstage, evenopts - to implement Redux Action for compatible with the Redux Middleware
- computed by
arg: taking major dataopts: taking metadataeffect?: (prevState: TState, actor: Actor) => TState- same as Redux Reducer: inputs
prevStateandactor, outputnextState - avoiding
rootReducerto make dynamics(import) happy, - avoiding nested state, could use
effectOnto scope effect node
- same as Redux Reducer: inputs
-
Declare
Storewitch extendsBehaviorSubject, implementsRedux Store:getState: () => TState- same as
ReduxStore.getStateor usegetValueorvaluewhich extendsBehaviorSubjectinstead
- same as
dispatch: (actor: Actor) => void- similar as
ReduxStore.dispath, but limit to dispatchActoronly
- similar as
subscribe: (nextState: TState) => Subscription- similar as
ReduxStore.subscribe, but return aSubscriptionand as an observer
- similar as
actor$: Subject<Actor>- A subject Actor
epicOn: (TEpic<TState>) => Subscription:TEpic<TState> = (actor$: Observable<Actor>, state$: Store<TState>): Observable<Actor>- inspired by redux-observable
- handling side effects
applyMiddleware: (...middlewares: IMiddleware<TRoot>[])=> void- same as
ReduxUtils.applyMiddleware
- same as
- drop
replaceReducer- there are no more rootReducer, and no need
ReduxUtils.combineReducerstoo.
- there are no more rootReducer, and no need
Example
import { Store, Actor, Volume, renderOn } from "@reactorx/core"
import { filter, map } from "rxjs/operators"
const testActor = Actor.of("test");
const ping = testActor.named<{ step?: number }, { o: string }>("ping").effectOn("ping", (state: any = 0, actor) => {
return state + (actor.arg.step || 1);
});
const pong = testActor.named("pong").effectOn("pong", (state: any = 0) => {
return state + 1;
});
const so$ = Store.create({ ping: 0, pong: 0 });
so$.applyMiddleware(() => (next) => (actor) => next(actor));
const pingStates: number[] = [];
const pongStates: number[] = [];
Volume.from(so$, (state) => state["ping"]).subscribe((nextState) => {
pingStates.push(nextState);
});
Volume.from(so$, (state) => state["pong"]).subscribe((nextState) => {
pongStates.push(nextState);
});
renderOn(so$, () => {
return null;
});
so$.epicOn((actor$) => {
return actor$.pipe(
filter(ping.is),
map(() => {
return pong.with({});
}),
);
});
for (let i = 0; i < 5; i++) {
ping.with({}).invoke(so$);
expect(so$.getState()).toEqual({
ping: 1 + i,
pong: 1 + i,
});
}
expect(pingStates).toEqual([0, 1, 2, 3, 4, 5]);
expect(pongStates).toEqual([0, 1, 2, 3, 4, 5]);
@reactorx/router 
Core rules copy form react-router without compatibility for old version. and provide:
useRouterinsteadwithRouterReactorxRouterrouterActorsfor navigate through dispatching actor- syncing
history.locationtoState["$$location"]
@reactorx/request 
base on axios, provide:
createRequestActor<TArg, TRespData, TRespErr>(name: string, (arg: TArg) => IRequestOpts: RequestActor<TArg, TRespData, TRespErr>- request actor builder
- epics for handles
RequestActorcreateCombineDuplicatedRequestEpicto unique requestcreateRequestEpicto send all request and resolve or reject matched response
Examples
see testings
@reactorx/form 
similar as redux-form