UNPKG

react-reducer-provider

Version:

Asynchronous/Synchronous React Centralized State with Hooks and HOC

348 lines (256 loc) 12.4 kB
// 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; }