react-sweet-state
Version:
Global + local state combining the best of Redux and Context API
332 lines (289 loc) • 9.95 kB
Flow
// @flow
/* eslint-disable no-redeclare */
import type { Node } from 'react';
/**
* ST: Full store state
* AC: Store actions
* SE: Selector output
* PR: Component props
* CPR: Container props
* SAA: Store action API
*/
type SetState<ST> = (partialState: $Shape<ST>) => void;
type GetState<ST> = () => $ReadOnly<ST>;
type StoreUnsubscribe = () => void;
export type RenderPropComponent<ST, AC> = (
state: ST,
actions: $Exact<BoundActions<AC>>
) => Node;
export type HookReturnValue<ST, AC> = [ST, $Exact<BoundActions<AC>>];
export type Store<ST, AC> = {|
key: string,
initialState: ST,
actions: AC,
containedBy?: ContainerComponent<any>,
handlers?: {
onInit?: () => (api: StoreActionApi<ST>, containerProps: any) => any,
onUpdate?: () => (api: StoreActionApi<ST>, containerProps: any) => any,
onDestroy?: () => (api: StoreActionApi<ST>, containerProps: any) => any,
onContainerUpdate?: () => (
api: StoreActionApi<ST>,
containerProps: any
) => any,
},
|};
export type StoreState<ST> = {|
getState: GetState<ST>,
setState: SetState<ST>,
resetState: () => void,
notify: () => void,
key: string,
subscribe: (listener: () => void) => StoreUnsubscribe,
mutator: SetState<ST>,
|};
type ExtractReturnType = <R>(
(api: StoreActionApi<any>, containerProps: any) => R
) => R;
export type StoreActionApi<ST> = {|
setState: SetState<ST>,
getState: GetState<ST>,
dispatch: <F>(actionThunk: F) => $Call<ExtractReturnType, F>,
|};
export type Action<ST, CPR = void, R = *> = (
api: StoreActionApi<ST>,
containerProps: CPR
) => R;
// prettier-ignore
type BoundAction<F, SAA = *, CPR = *> =
& (<A, B, C, D, E>(a: A, b: B, c: C, d: D, e: E) => $Call<$Call<F, A, B, C, D, E>, SAA, CPR>)
& (<A, B, C, D>(a: A, b: B, c: C, d: D) => $Call<$Call<F, A, B, C, D>, SAA, CPR>)
& (<A, B, C>(a: A, b: B, c: C) => $Call<$Call<F, A, B, C>, SAA, CPR>)
& (<A, B>(a: A, b: B) => $Call<$Call<F, A, B>, SAA, CPR>)
& (<A>(a: A) => $Call<$Call<F, A>, SAA, CPR>)
& (() => $Call<$Call<F>, SAA, CPR>);
type MapBoundAction = <F>(F) => BoundAction<F>;
export type BoundActions<AC> = $ObjMap<AC, MapBoundAction>;
export type StoreInstance<ST, AC> = {
store: StoreState<ST>,
actions: BoundActions<AC>,
};
declare export class Registry {
stores: Map<string, StoreInstance<any, any>>;
initStore: <ST, AC>(
store: Store<ST, AC>,
key: string
) => StoreInstance<ST, AC>;
getStore: <ST, AC>(
store: Store<ST, AC>,
scopeId?: string
) => StoreInstance<ST, AC>;
hasStore: <ST, AC>(store: Store<ST, AC>, scopeId?: string) => boolean;
deleteStore: <ST, AC>(store: Store<ST, AC>, scopeId?: string) => void;
}
declare export var defaultRegistry: Registry;
type MiddlewareResult = any;
export type Middleware = (
storeState: StoreState<any>
) => (next: (arg: any) => MiddlewareResult) => (arg: any) => MiddlewareResult;
declare export var defaults: {
batchUpdates: boolean,
devtools: boolean | ((storeState: StoreState<any>) => Object),
middlewares: Set<Middleware>,
mutator: <ST>(currentState: ST, setStateArg: any) => ST,
};
declare export function batch(callback: () => any): void;
export type ContainerComponent<PR = void> = React$ComponentType<{|
scope?: string,
isGlobal?: boolean,
children: Node,
...PR,
|}>;
export type SubscriberComponent<ST, AC, PR = void> = React$ComponentType<{|
children: RenderPropComponent<ST, AC>,
...PR,
|}>;
export type HookFunction<ST, AC, PR = void> = (
props?: PR
) => HookReturnValue<ST, AC>;
export type HookActionsFunction<AC> = () => $Exact<BoundActions<AC>>;
export type HookStateFunction<ST, PR = void> = (props?: PR) => ST;
/**
* createStore
*/
declare export function createStore<ST: { ... }, AC, CPR = void>({|
initialState: ST,
actions: AC,
name?: string,
containedBy?: ContainerComponent<CPR>,
handlers?: {
onInit?: () => (api: StoreActionApi<ST>, containerProps: CPR) => any,
onUpdate?: () => (api: StoreActionApi<ST>, containerProps: CPR) => any,
onDestroy?: () => (api: StoreActionApi<ST>, containerProps: CPR) => any,
onContainerUpdate?: () => (
api: StoreActionApi<ST>,
containerProps: CPR
) => any,
},
|}): Store<ST, AC>;
/**
* createContainer
*/
declare export function createContainer<CPR>(config?: {|
displayName?: string,
|}): ContainerComponent<CPR>;
declare export function createContainer<ST, AC, CPR>(
store: Store<ST, AC>,
options?: {|
onInit?: () => (api: StoreActionApi<ST>, containerProps: CPR) => any,
onUpdate?: () => (api: StoreActionApi<ST>, containerProps: CPR) => any,
onCleanup?: () => (api: StoreActionApi<ST>, containerProps: CPR) => any,
displayName?: string,
|}
): ContainerComponent<CPR>;
/**
* createSubscriber
*/
declare export function createSubscriber<ST, AC>(
store: Store<ST, AC>,
options?: {|
displayName?: string,
|}
): SubscriberComponent<ST, AC, {||}>;
// Flow does not support null properly to refine override :(
// declare export function createSubscriber<ST, AC>(
// store: Store<ST, AC>,
// options: {|
// selector: null,
// displayName?: string,
// |}
// ): SubscriberComponent<undefined, AC, {||}>;
declare export function createSubscriber<ST, AC, SE, PR>(
store: Store<ST, AC>,
options: {|
selector: null | ((state: ST, props: PR) => SE),
displayName?: string,
|}
): SubscriberComponent<SE, AC, PR>;
/**
* createHook
*/
declare export function createHook<ST, AC>(
store: Store<ST, AC>
): HookFunction<ST, AC, void>;
// Flow does not support null properly to refine override :(
// declare export function createHook<ST, AC>(
// store: Store<ST, AC>,
// options: {|
// selector: null,
// |},
// ): () => HookReturnValue<void, AC>;
declare export function createHook<ST, AC, SE, PR>(
store: Store<ST, AC>,
options: {|
selector: null | ((state: ST, props: PR) => SE),
|}
): HookFunction<SE, AC, PR>;
declare export function createActionsHook<ST, AC>(
store: Store<ST, AC>
): HookActionsFunction<AC>;
declare export function createStateHook<ST, AC>(store: Store<ST, AC>): () => ST;
declare export function createStateHook<ST, AC, SE, PR>(
store: Store<ST, AC>,
options: {|
selector: (state: ST, props: PR) => SE,
|}
): HookStateFunction<SE, PR>;
/**
* createSelector
*/
declare type InputSelector<-ST, PR, SE> = (state: ST, props: PR) => SE;
declare type OutputSelector<-ST, PR, SE> = {
(state: ST, props: PR): SE,
resultFunc(...args: any[]): SE,
dependencies: any[],
};
declare export function createSelector<ST, PR, SE, T1>(
selector1: InputSelector<ST, PR, T1>,
resultFn: (arg1: T1) => SE
): OutputSelector<ST, PR, SE>;
declare export function createSelector<ST, PR, SE, T1>(
selectors: [InputSelector<ST, PR, T1>],
resultFn: (arg1: T1) => SE
): OutputSelector<ST, PR, SE>;
declare export function createSelector<ST, PR, SE, T1, T2>(
selector1: InputSelector<ST, PR, T1>,
selector2: InputSelector<ST, PR, T2>,
resultFn: (arg1: T1, arg2: T2) => SE
): OutputSelector<ST, PR, SE>;
declare export function createSelector<ST, PR, SE, T1, T2>(
selectors: [InputSelector<ST, PR, T1>, InputSelector<ST, PR, T2>],
resultFn: (arg1: T1, arg2: T2) => SE
): OutputSelector<ST, PR, SE>;
declare export function createSelector<ST, PR, SE, T1, T2, T3>(
selector1: InputSelector<ST, PR, T1>,
selector2: InputSelector<ST, PR, T2>,
selector3: InputSelector<ST, PR, T3>,
resultFn: (arg1: T1, arg2: T2, arg3: T3) => SE
): OutputSelector<ST, PR, SE>;
declare export function createSelector<ST, PR, SE, T1, T2, T3>(
selectors: [
InputSelector<ST, PR, T1>,
InputSelector<ST, PR, T2>,
InputSelector<ST, PR, T3>
],
resultFn: (arg1: T1, arg2: T2, arg3: T3) => SE
): OutputSelector<ST, PR, SE>;
declare export function createSelector<ST, PR, SE, T1, T2, T3, T4>(
selector1: InputSelector<ST, PR, T1>,
selector2: InputSelector<ST, PR, T2>,
selector3: InputSelector<ST, PR, T3>,
selector4: InputSelector<ST, PR, T4>,
resultFn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4) => SE
): OutputSelector<ST, PR, SE>;
declare export function createSelector<ST, PR, SE, T1, T2, T3, T4>(
selectors: [
InputSelector<ST, PR, T1>,
InputSelector<ST, PR, T2>,
InputSelector<ST, PR, T3>,
InputSelector<ST, PR, T4>
],
resultFn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4) => SE
): OutputSelector<ST, PR, SE>;
declare export function createSelector<ST, PR, SE, T1, T2, T3, T4, T5>(
selector1: InputSelector<ST, PR, T1>,
selector2: InputSelector<ST, PR, T2>,
selector3: InputSelector<ST, PR, T3>,
selector4: InputSelector<ST, PR, T4>,
selector5: InputSelector<ST, PR, T5>,
resultFn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5) => SE
): OutputSelector<ST, PR, SE>;
declare export function createSelector<ST, PR, SE, T1, T2, T3, T4, T5>(
selectors: [
InputSelector<ST, PR, T1>,
InputSelector<ST, PR, T2>,
InputSelector<ST, PR, T3>,
InputSelector<ST, PR, T4>,
InputSelector<ST, PR, T5>
],
resultFn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5) => SE
): OutputSelector<ST, PR, SE>;
declare export function createSelector<ST, PR, SE, T1, T2, T3, T4, T5, T6>(
selector1: InputSelector<ST, PR, T1>,
selector2: InputSelector<ST, PR, T2>,
selector3: InputSelector<ST, PR, T3>,
selector4: InputSelector<ST, PR, T4>,
selector5: InputSelector<ST, PR, T5>,
selector6: InputSelector<ST, PR, T6>,
resultFn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5, arg6: T6) => SE
): OutputSelector<ST, PR, SE>;
declare export function createSelector<ST, PR, SE, T1, T2, T3, T4, T5, T6>(
selectors: [
InputSelector<ST, PR, T1>,
InputSelector<ST, PR, T2>,
InputSelector<ST, PR, T3>,
InputSelector<ST, PR, T4>,
InputSelector<ST, PR, T5>,
InputSelector<ST, PR, T6>
],
resultFn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5, arg6: T6) => SE
): OutputSelector<ST, PR, SE>;