AsyncReducerProvider
· SyncReducerProvider
· AsyncMapperProvider
· SyncMapperProvider
Definition
SyncReducerProvider
& AsyncReducerProvider
are React Components which defines a React Context that allows to Manage State using Flux, an application architecture that handles application states in a unidirectional way.
- Flux is composed basically with:
- Stores: keeps states of the app (or components).
- Reducer: function that changes the State based on an Action and the previous State.
- Actions: triggers changes in Store.
- Dispatcher: sends Actions to the Store.
- Mainly the bridge between the Store and Components.
- Stores: keeps states of the app (or components).
Each SyncReducerProvider
or AsyncReducerProvider
is equivalent to a Flux stream:
Similarly, SyncMapperProvider
and AsyncMapperProvider
have the following stream:
AsyncReducerProvider
, SyncReducerProvider
, AsyncMapperProvider
& SyncMapperProvider
are React “Special” Elements defined by 3 properties:
properties:
1 . initialState
: inception state for the component or a function to create initial state.
2 . id ?: string | number | symbol
: constitutes the identifier of the SyncReducerProvider
, AsyncReducerProvider
, SyncMapperProvider
or AsyncMapperProvider
, which is useful when using more than 1 react-reducer-provider
provider.
AsyncReducerProvider
& SyncReducerProvider
have the following property:
3 . reducer
: an asynchronous or synchronous function that will receive the current state and an action to produce a new state [1].
function syncReduce<STATE, ACTION>(prevState: STATE, action: ACTION): STATE
<SyncReducerProvider
id='someNamedReducer'
reducer={syncReduce}
initialState={initialState}
>
{children}
</SyncReducerProvider>
or
function asyncReduce<STATE, ACTION>(prevState: STATE, action: ACTION): Promise<STATE>
<AsyncReducerProvider
id={12345}
reducer={asyncReduce}
initialState={() => initialState}
>
{children}
</AsyncReducerProvider>
AsyncMapperProvider
& SyncMapperProvider
have the following property:
3 . mapper
: an asynchronous or synchronous function that will receive an action to produce a new state [1].
function asyncMap<STATE, ACTION>(action: ACTION): Promise<STATE>
<AsyncMapperProvider
id={12345}
mapper={asyncMap}
initialState={initialState}
>
{children}
</AsyncMapperProvider>
or
function syncMap<STATE, ACTION>(action: ACTION): STATE
<SyncMapperProvider
id='someNamedMapper'
mapper={syncMap}
initialState={() => initialState}
>
{children}
</SyncMapperProvider>
[1] No check is made for asynchronous reducer/mapper, i.e. use
AsyncReducerProvider
/AsyncMapperProvider
for asynchronous reducer/mapper to avoid setting state to aPromise
(unless that is intentional).
Properties change
Any change to the initial Properties for mounted State Providers will be ignored for rendering, in order to improve performance, but not for processing, i.e. props changes will not cause re-rendering, although the new reducers/mappers will be used for calculating new states.
id
change is totally ignored.- new
reducer
/mapper
will be used.- If
reducer
/mapper
are set tonull
orundefined
, then it will disabled the processor and return the last state achieved for every following dispatching until a newreducer
/mapper
is set again.
- If
- new
initialState
will be ignored.
A example can be checked on line at gmullerb-react-mapper-provider with a function as a state codesandbox:
If unmounted, olds state will be lost when mounted again and a new fresh state will be used.
A Function as State
To initialize the state as a function, initialState
must be set with a function:
<SyncMapperProvider
id='someNamedMapper'
mapper={syncMap}
initialState={() => (x, y) => x + y}
>
{children}
</SyncMapperProvider>
A example can be checked on line at gmullerb-react-mapper-provider with a function as a state codesandbox:
Synchronous Reducer/Mapper => SyncReducerProvider
/SyncMapperProvider
SyncReducerProvider
<SyncReducerProvider
id='someNamedReducer'
reducer={syncReduce}
initialState={initialState}
>
{children}
</SyncReducerProvider>
-
reducer
will be a synchronous function that will receive the current state and an action to produce a new state.function syncReducer<STATE, ACTION>(prevState: STATE, action: ACTION): STATE
e.g.:
function reduce(prevState, action) {
switch (action) {
case 'ACTION1':
return prevState + 1
case 'ACTION2':
return prevState - 1
default:
return prevState
}
}
SyncMapperProvider
<SyncMapperProvider
id='someNamedMapper'
mapper={syncMap}
initialState={initialState}
>
{children}
</SyncMapperProvider>
-
mapper
will be a synchronous function that will receive an action to produce a new state.sync function syncMapper<STATE, ACTION>(action: ACTION):STATE
e.g.:
async function map(action) {
switch (action) {
case 'ACTION1':
return someSyncProcess1()
case 'ACTION2':
return someValue
default:
return prevState
}
}
Dispatcher
when accessing the Mapper/Reducer Provider, the dispatcher
will be also a synchronous function:
An
SyncReducerProvider
example can be checked on line at gmullerb-react-reducer-provider codesandbox:
AnSyncMapperProvider
example can be checked on line at gmullerb-react-mapper-provider codesandbox:
Asynchronous Reducer/Mapper => AsyncReducerProvider
/AsyncMapperProvider
AsyncReducerProvider
<AsyncReducerProvider
id='someNamedReducer'
reducer={asyncReduce}
initialState={initialState}
>
{children}
</AsyncReducerProvider>
-
reducer
will be an asynchronous function that will receive the current state and an action to produce aPromise
of the new state.async function asyncReducer<STATE, ACTION>(prevState: STATE, action: ACTION): Promise<STATE>
e.g.:
async function reduce(prevState, action) {
switch (action) {
case 'ACTION1':
return await someAsyncProcess1(prevState)
case 'ACTION2':
return someAsyncProcess2(prevState)
default:
return prevState
}
}
AsyncMapperProvider
<AsyncMapperProvider
id='someNamedMapper'
mapper={asyncMap}
initialState={initialState}
>
{children}
</AsyncMapperProvider>
-
mapper
will be an asynchronous function that will receive an action to produce aPromise
of the new state.async function asyncMapper<STATE, ACTION>(action: ACTION): Promise<STATE>
e.g.:
async function map(action) {
switch (action) {
case 'ACTION1':
return await someAsyncProcess1()
case 'ACTION2':
return someAsyncProcess2()
default:
return prevState
}
}
Dispatcher
-
when accessing the Reducer/Mapper Provider, the
dispatcher
will be also a asynchronous function:async function dispatch<ACTION>(action: ACTION): Promise<void>
e.g.:
dispatch('ACTION2').then(someProcess())
When the
dispatch
is resolved is an indication that the state was change, but not of any required re-rendering being done.
AnAsyncReducerProvider
can be checked on line at gmullerb-react-reducer-provider codesandbox:
AnAsyncMapperProvider
example can be checked on line at gmullerb-react-mapper-provider-async codesandbox:
AlthoughAsyncReducerProvider
can be used for synchronous reducer/dispatcher (check AsyncReducerProviderWithSync.test.jsx), It is not is purpose and implementation is suitable for asynchronous processes, long story short, for synchronous processes, useSyncReducerProvider
.
Examples of use can be looked at basecode-react-ts and basecode-cordova-react-ts.
Dispatcher
Dispatcher
is the proxy between the Remote component and the and returns the new State or a Promise of the new State:
Synchronous dispatcher:
const newState = dispatch(action)
Asynchronous dispatcher:
dispatch(action).then(newState => console.info(newState))
If new State is not required, then return value can be ignored:
dispatch(action)
Returned value is useful when using
useReducerDispatcher
,useMapperDispatcher
,injectReducerDispatcher
,injectMapperDispatcher
. By default, when using typings return value is ignored, i.e isvoid
orPromise<void>
. Examples can be seen at:SyncReducerProvider.test.jsx
andAsyncReducerProviderWithAsync.test.jsx
. Examples of use can be looked at basecode-react-ts and basecode-cordova-react-ts.
Exceptions
If reducer or mapper may throw an exception, then the code calling the dispatcher should handle this situations:
synchronous reducer/mapper
try {
dispatch('Tag1', 'ACTION1')
..
}
catch(error)
{
..
}
asynchronous reducer/mapper
dispatch('Tag1', 'ACTION1')
.then(..)
.catch(error => ..)
}
- Remember you design the reducer/mapper, so you must be aware if exceptions are possible.
- In case of exceptions is better to handle them inside reducer/mapper.
Extra parameters
Dispatcher can send any number of additional arguments:
Synchronous:
dispatch('ACTION2', arg1, arg2, argN)
Asynchronous:
dispatch('ACTION2', arg1, arg2, argN).then(someProcess())
Then, respectively:
- Reducer can have any number of additional parameters, and use them as pleased:
async function reduce(prevState, action, param1, param2, paramN) {
switch (action) {
case 'ACTION1':
return await someAsyncProcess1(prevState, param1, param2, paramN)
case 'ACTION2':
return someAsyncProcess2(prevState, param1, param2, paramN)
default:
return prevState
}
}
- Mapper can have any number of additional parameters, and use them as pleased:
async function map(action, param1, param2, paramN) {
switch (action) {
case 'ACTION1':
return await someAsyncProcess1(param1, param2, paramN)
case 'ACTION2':
return someAsyncProcess2(param1, param2, paramN)
default:
return prevState
}
}
An example can be checked on line at gmullerb-react-reducer-provider-async codesandbox:
This makes “obsolete” the Action, but at the end can be matter of preference.
Reducer/Mapper Consumption
Function Components - Hooks
Class Components - HOC
More Documentation
useReducer
·useReducerState
·useReducerDispatcher
·useMapper
·useMapperState
·useMapperDispatcher
.injectReducer
·injectReducerState
·injectReducerDispatcher
·injectMapper
·injectMapperState
·injectMapperDispatcher
.- Singleton.
- Nesting.
- Combining/Blending - Tagged Reducers/Mappers.
AsyncTaggedReducerProvider
·SyncTaggedReducerProvider
·AsyncTaggedMapperProvider
·SyncTaggedMapperProvider
.useTaggedAny
·useTaggedReducer
·useTaggedReducerState
·useTaggedReducerDispatcher
·useTaggedMapper
·useTaggedMapperState
·useTaggedMapperDispatcher
.injectTaggedAny
·injectTaggedReducer
·injectTaggedReducerState
·injectTaggedReducerDispatcher
·injectTaggedMapper
·injectTaggedMapperState
·injectTaggedMapperDispatcher
.
- Typings.
- With Injection.
- With Actions Creators.
- Testing.
- Examples from tests.
- Online examples.
- Typings’ examples from tests.
- Extending/Developing.