react-reducer-provider
Version:
Asynchronous/Synchronous React Centralized State with Hooks and HOC
348 lines (256 loc) • 12.4 kB
Flow
// Copyright (c) 2020 Gonzalo Müller Bravo.
import React from 'react'
import type { Node, AbstractComponent } from 'react'
// Provider Component
/////////////////////
export type Id = string | number | symbol | null
export interface ProviderProps {
id?: Id;
children: Node;
}
export interface StateProviderProps<STATE> extends ProviderProps {
initialState?: (() => STATE) | STATE;
}
// Reducer Component Definition
///////////////////////////////
export interface ReducerProps<STATE, REDUCER> extends StateProviderProps<STATE> {
/**
* Must always be assigned, although can be 'null' or 'undefined'.
*/
reducer: REDUCER | null | typeof(undefined)
}
export interface SyncReducer<STATE, ACTION> {
(prevState: STATE, action: ACTION, ...args: $ReadOnlyArray<any>): STATE
}
export interface SyncReducerProps<STATE, ACTION> extends ReducerProps<STATE, SyncReducer<STATE, ACTION>> {}
declare export class SyncReducerProvider<STATE, ACTION> extends React.Component<SyncReducerProps<STATE, ACTION>> {}
export interface AsyncReducer<STATE, ACTION> {
(prevState: STATE, action: ACTION, ...args: $ReadOnlyArray<any>): Promise<STATE>
}
export interface AsyncReducerProps<STATE, ACTION> extends ReducerProps<STATE, AsyncReducer<STATE, ACTION>> {}
declare export class AsyncReducerProvider<STATE, ACTION> extends React.Component<AsyncReducerProps<STATE, ACTION>> {}
// Mapper Component Definition
//////////////////////////////
export interface MapperProps<STATE, MAPPER> extends StateProviderProps<STATE> {
/**
* Must always be assigned, although can be 'null' or 'undefined'.
*/
mapper: MAPPER | null | typeof(undefined)
}
export interface SyncMapper<STATE, ACTION> {
(action: ACTION, ...args: $ReadOnlyArray<any>): STATE
}
export interface SyncMapperProps<STATE, ACTION> extends MapperProps<STATE, SyncMapper<STATE, ACTION>> {}
declare export class SyncMapperProvider<STATE, ACTION> extends React.Component<SyncMapperProps<STATE, ACTION>> {}
export interface AsyncMapper<STATE, ACTION> {
(action: ACTION, ...args: $ReadOnlyArray<any>): Promise<STATE>
}
export interface AsyncMapperProps<STATE, ACTION> extends MapperProps<STATE, AsyncMapper<STATE, ACTION>> {}
declare export class AsyncMapperProvider<STATE, ACTION> extends React.Component<AsyncMapperProps<STATE, ACTION>> {}
// Actuator Component Definition
////////////////////////////////
export interface ActuatorProps<ACTUATOR: Function = Function> extends ProviderProps {
/**
* Must always be assigned, although can be 'null' or 'undefined'.
*/
actuator: ACTUATOR | null | typeof(undefined)
}
declare class ActuatorProvider<ACTUATOR: Function = Function> extends React.Component<ActuatorProps<ACTUATOR>> {}
// Providers Consumption
////////////////////////
export type Sync<RESULT = any> = RESULT
export type Async<RESULT = any> = Promise<RESULT>
export type DispatcherResult<RESULT = any> = Async<void | RESULT> | Sync<void | RESULT>
export interface Dispatcher<ACTION, DISPATCH: Async<> | Sync<> = Sync<void>> {
(value: ACTION, ...args: $ReadOnlyArray<any>): DISPATCH
}
export interface ProviderValueObject {
/**
* provider id
*/
+provider: Id
}
export interface StateProviderValueObject<
STATE,
ACTION,
DISPATCH: Async<void | STATE> | Sync<void | STATE> = Sync<void>
> extends ProviderValueObject {
+state: STATE;
+dispatch: Dispatcher<ACTION, DISPATCH>;
}
export type ProviderValueTuple<
STATE,
ACTION,
DISPATCH: Async<void | STATE> | Sync<void | STATE> = Sync<void>
> = [STATE, Dispatcher<ACTION, DISPATCH>, Id]
export type ProviderValue<
STATE,
ACTION,
DISPATCH: Async<void | STATE> | Sync<void | STATE> = Sync<void>
> = StateProviderValueObject<STATE, ACTION, DISPATCH> & ProviderValueTuple<STATE, ACTION, DISPATCH>
declare export function useReducer<STATE, ACTION, DISPATCH: Async<void | STATE> | Sync<void | STATE> = Sync<void>>(
id?: Id
): ProviderValue<STATE, ACTION, DISPATCH>
declare export function useReducerState<STATE>(id?: Id): STATE
declare export function useReducerDispatcher<ACTION, DISPATCH: Async<> | Sync<> = Sync<void>>(
id?: Id
): Dispatcher<ACTION, DISPATCH>
declare export function useMapper<STATE, ACTION, DISPATCH: Async<void | STATE> | Sync<void | STATE> = Sync<void>>(
id?: Id
): ProviderValue<STATE, ACTION, DISPATCH>
declare export function useMapperState<STATE>(id?: Id): STATE
declare export function useMapperDispatcher<ACTION, DISPATCH: Async<> | Sync<> = Sync<void>>(
id?: Id
): Dispatcher<ACTION, DISPATCH>
declare export function injectReducer<INJECTED_PROP: {}, PROPS: {}>(
ComponentClass: AbstractComponent<PROPS>, injectedPropName: $Keys<INJECTED_PROP>, id?: Id
): AbstractComponent<$Diff<PROPS, INJECTED_PROP>>
declare export function injectReducerState<INJECTED_PROP: {}, PROPS: {}>(
ComponentClass: AbstractComponent<PROPS>, injectedPropName: $Keys<INJECTED_PROP>, id?: Id
): AbstractComponent<$Diff<PROPS, INJECTED_PROP>>
declare export function injectReducerDispatcher<INJECTED_PROP: {}, PROPS: {}>(
ComponentClass: AbstractComponent<PROPS>, injectedPropName: $Keys<INJECTED_PROP>, id?: Id
): AbstractComponent<$Diff<PROPS, INJECTED_PROP>>
declare export function injectMapper<INJECTED_PROP: {}, PROPS: {}>(
ComponentClass: AbstractComponent<PROPS>, injectedPropName: $Keys<INJECTED_PROP>, id?: Id
): AbstractComponent<$Diff<PROPS, INJECTED_PROP>>
declare export function injectMapperState<INJECTED_PROP: {}, PROPS: {}>(
ComponentClass: AbstractComponent<PROPS>, injectedPropName: $Keys<INJECTED_PROP>, id?: Id
): AbstractComponent<$Diff<PROPS, INJECTED_PROP>>
declare export function injectMapperDispatcher<INJECTED_PROP: {}, PROPS: {}>(
ComponentClass: AbstractComponent<PROPS>, injectedPropName: $Keys<INJECTED_PROP>, id?: Id
): AbstractComponent<$Diff<PROPS, INJECTED_PROP>>
// Actuator Consumption
///////////////////////
export type ActuatorProviderValue<ACTUATOR: Function = Function> = ACTUATOR & ProviderValueObject
declare export function useActuator<ACTUATOR: Function = Function> (
id?: Id
): ActuatorProviderValue<ACTUATOR>
// Tagged Provider Component
////////////////////////////
export interface TaggedProviderProps {
id?: Id;
children: Node;
}
export type TaggedProcessor<PROCESSOR> = [ Id, PROCESSOR, any ] | [ Id, PROCESSOR ]
// Tagged Reducer Component Definition
//////////////////////////////////////
export interface TaggedReducerProps<REDUCER> extends TaggedProviderProps {
/**
* Must always be assigned, although can be 'null' or 'undefined'.
*/
reducers: REDUCER[] | null | typeof(undefined)
}
export type SyncTaggedReducer = TaggedProcessor<SyncReducer<any, any>>
export interface SyncTaggedReducerProps extends TaggedReducerProps<SyncTaggedReducer> {}
declare export class SyncTaggedReducerProvider extends React.Component<SyncTaggedReducerProps> {}
export type AsyncTaggedReducer = TaggedProcessor<AsyncReducer<any, any>>
export interface AsyncTaggedReducerProps extends TaggedReducerProps<AsyncTaggedReducer> {}
declare export class AsyncTaggedReducerProvider extends React.Component<AsyncTaggedReducerProps> {}
// Tagged Mapper Component Definition
//////////////////////////////////////
export interface TaggedMapperProps<MAPPER> extends TaggedProviderProps {
/**
* Must always be assigned, although can be 'null' or 'undefined'.
*/
mappers: MAPPER[] | null | typeof(undefined)
}
export type SyncTaggedMapper = TaggedProcessor<SyncMapper<any, any>>
export interface SyncTaggedMapperProps extends TaggedMapperProps<SyncTaggedMapper> {}
declare export class SyncTaggedMapperProvider extends React.Component<SyncTaggedMapperProps> {}
export type AsyncTaggedMapper = TaggedProcessor<AsyncMapper<any, any>>
export interface AsyncTaggedMapperProps extends TaggedMapperProps<AsyncTaggedMapper> {}
declare export class AsyncTaggedMapperProvider extends React.Component<AsyncTaggedMapperProps> {}
// Tagged Actuator Component Definition
///////////////////////////////////////
export interface TaggedActuatorProps<ACTUATORS: TaggedProcessor<Function>[] = TaggedProcessor<Function>[]> extends ProviderProps {
/**
* Must always be assigned, although can be 'null' or 'undefined'.
*/
actuators: ACTUATORS | null | typeof(undefined)
}
declare export class TaggedActuatorProvider<ACTUATORS: TaggedProcessor<Function>[] = TaggedProcessor<Function>[]>
extends React.Component<TaggedActuatorProps<ACTUATORS>> {}
// Tagged Consumption
/////////////////////
export interface TaggedProviderValueObject<
STATE,
ACTION,
DISPATCH: Async<void | STATE> | Sync<void | STATE> = Sync<void>
> extends StateProviderValueObject<STATE, ACTION, DISPATCH> {
+tag: Id;
}
export type TaggedProviderValueTuple<
STATE,
ACTION,
DISPATCH: Async<void | STATE> | Sync<void | STATE> = Sync<void>
> = [STATE, Dispatcher<ACTION, DISPATCH>, Id, Id]
export type TaggedProviderValue<
STATE,
ACTION,
DISPATCH: Async<void | STATE> | Sync<void | STATE> = Sync<void>
> = TaggedProviderValueObject<STATE, ACTION, DISPATCH> & TaggedProviderValueTuple<STATE, ACTION, DISPATCH>
export interface TaggedProviderGetter<
ANY_ID: Id = Id,
ANY_STATE = any,
ANY_ACTION = any,
ANY_DISPATCH: DispatcherResult<ANY_STATE> = Sync<void>
> {
+get: (tag: ANY_ID) => TaggedProviderValue<ANY_STATE, ANY_ACTION, ANY_DISPATCH>
}
declare export function useTaggedAny<
ANY_ID: Id = Id,
ANY_STATE = any,
ANY_ACTION = any,
ANY_DISPATCH: DispatcherResult<ANY_STATE> = Sync<void>>(
id?: Id
): TaggedProviderGetter<ANY_ID, ANY_STATE, ANY_ACTION, ANY_DISPATCH>
declare export function useTaggedReducer<STATE, ACTION, DISPATCH: Async<void | STATE> | Sync<void | STATE> = Sync<void>>(
tag: Id, id?: Id
): TaggedProviderValue<STATE, ACTION, DISPATCH>
declare export function useTaggedReducerState<STATE>(tag: Id, id?: Id): STATE
declare export function useTaggedReducerDispatcher<ACTION, DISPATCH: Async<> | Sync<> = Sync<void>>(
tag: Id, id?: Id
): Dispatcher<ACTION, DISPATCH>
declare export function useTaggedMapper<STATE, ACTION, DISPATCH: Async<void | STATE> | Sync<void | STATE> = Sync<void>>(
tag: Id, id?: Id
): TaggedProviderValue<STATE, ACTION, DISPATCH>
declare export function useTaggedMapperState<STATE>(tag: Id, id?: Id): STATE
declare export function useTaggedMapperDispatcher<ACTION, DISPATCH: Async<> | Sync<> = Sync<void>>(
tag: Id, id?: Id
): Dispatcher<ACTION, DISPATCH>
declare export function injectTaggedAny<INJECTED_PROP: {}, PROPS: {}>(
ComponentClass: AbstractComponent<PROPS>, injectedPropName: $Keys<INJECTED_PROP>, id?: Id
): AbstractComponent<$Diff<PROPS, INJECTED_PROP>>
declare export function injectTaggedReducer<INJECTED_PROP: {}, PROPS: {}>(
ComponentClass: AbstractComponent<PROPS>, injectedPropName: $Keys<INJECTED_PROP>, tag: Id, id?: Id
): AbstractComponent<$Diff<PROPS, INJECTED_PROP>>
declare export function injectTaggedReducerState<INJECTED_PROP: {}, PROPS: {}>(
ComponentClass: AbstractComponent<PROPS>, injectedPropName: $Keys<INJECTED_PROP>, tag: Id, id?: Id
): AbstractComponent<$Diff<PROPS, INJECTED_PROP>>
declare export function injectTaggedReducerDispatcher<INJECTED_PROP: {}, PROPS: {}>(
ComponentClass: AbstractComponent<PROPS>, injectedPropName: $Keys<INJECTED_PROP>, tag: Id, id?: Id
): AbstractComponent<$Diff<PROPS, INJECTED_PROP>>
declare export function injectTaggedMapper<INJECTED_PROP: {}, PROPS: {}>(
ComponentClass: AbstractComponent<PROPS>, injectedPropName: $Keys<INJECTED_PROP>, tag: Id, id?: Id
): AbstractComponent<$Diff<PROPS, INJECTED_PROP>>
declare export function injectTaggedMapperState<INJECTED_PROP: {}, PROPS: {}>(
ComponentClass: AbstractComponent<PROPS>, injectedPropName: $Keys<INJECTED_PROP>, tag: Id, id?: Id
): AbstractComponent<$Diff<PROPS, INJECTED_PROP>>
declare export function injectTaggedMapperDispatcher<INJECTED_PROP: {}, PROPS: {}>(
ComponentClass: AbstractComponent<PROPS>, injectedPropName: $Keys<INJECTED_PROP>, tag: Id, id?: Id
): AbstractComponent<$Diff<PROPS, INJECTED_PROP>>
// Tagged Actuator Consumption
///////////////////////
declare export function useTaggedActuator<ACTUATOR: Function = Function> (
tag: Id, id?: Id
): ActuatorProviderValue<ACTUATOR>
// Helpers
//////////
export interface AnyAsyncDispatcher<ACTION = any, DISPATCH: Async<> = Async<void>> {
(value: ACTION, ...args: $ReadOnlyArray<any>): DISPATCH
}
export interface Action<TYPE, DATA = typeof undefined> {
type: TYPE;
data?: DATA;
}