useReducer
· useReducerState
· useReducerDispatcher
· useMapper
· useMapperState
· useMapperDispatcher
(React ≥ 16.8.0)
Consumption
Reducer or Mapper will never be accessible directly from children
elements, they will be able to access the State and/or Dispatcher.
There are different ways of doing this:
useReducer
, which give access both State andDispatcher
.useReducerDispatcher
, which give access only theDispatcher
.useReducerState
, which give access only the State.
or
useMapper
, which give access both State andDispatcher
.useMapperDispatcher
, which give access only theDispatcher
.useMapperState
, which give access only the State.
When using
useReducer
/useMapper
,useReducerDispatcher
/useMapperDispatcher
and/oruseReducerState
/useMapperState
, Be Aware that they useReact.useContext
and quote: ‘A component calling useContext will always re-render when the context value changes’, in this case whenstate
changes, therefore when usinguseReducerDispatcher
/useMapperDispatcher
although it not depends “directly” onstate
the component will be re-render whenstate
changes. Final words, useSyncMapperProvider
and/orAsyncMapperProvider
,SyncReducerProvider
and/orAsyncReducerProvider
everywhere is required and useuseReducer
/useMapper
,useReducerDispatcher
/useMapperDispatcher
and/oruseReducerState
/useMapperState
wisely (small scopes, as close to where is required with small amount of children). If children re-render is too expensive thenReact.useMemo
:
const FunComponent1 = () => {
const dispatch = useReducerDispatcher('testNamedReducer10')
return React.useMemo(() => (
<RelatedChildComponent
onClick={dispatch}
/>
), [dispatch])
}
(check test case ‘should get the same dispatcher references after state changes’ at SyncReducerProvider.test.jsx or AsyncReducerProviderWithAsync.test.jsx)
useReducer
/useMapper
useReducer(id)
useMapper(id)
parameters:
id ?: string | number | symbol
: constitutes the identifier (name, number or symbol) of theSyncReducerProvider
,AsyncReducerProvider
,SyncMapperProvider
orAsyncMapperProvider
being accessed.
returns:
a tuple containing:
[0]
: thestate
.[1]
: thedispatcher
.[2]
: the provider id.state
: thestate
.dispatch
: thedispatcher
.provider
: the provider id.
Trying to reassign
state
,dispatch
,provider
,[0]
,[1]
or[2]
will result in aTypeError: Cannot assign to read only property '..' of object '[object Array]'
Exception.
Trying to add new fields will result in aTypeError: can't define property "..": Array is not extensible
Exception.
For purpose of avoiding re-renders and/or improving performance always use the elements of the tuple as reference, never the tuple perse, keep in mind that the tuple that is returned may change but elements will only change when state changes. Also, can useuseEffect/useMemo/useCallback
. This is not an “issue” when using the elements of the tuple as reference or when usinguse*Dispatcher
oruse*State
.
import { useReducer } from 'react-reducer-provider'
import React from 'react'
export default function SomeComponent1() {
const [ state, dispatch ] = useReducer('someNamedReducer')
return (
<button onClick={() => dispatch('ACTION1')}>
Go up (from {state})!
</button>
)
}
or
import { useReducer } from 'react-reducer-provider'
import React from 'react'
export default function SomeComponent1() {
const { state, dispatch } = useReducer('someNamedReducer')
return (
<button onClick={() => dispatch('ACTION1')}>
Go up (from {state})!
</button>
)
}
useReducerDispatcher
/useMapperDispatcher
useReducerDispatcher(id)
useMapperDispatcher(id)
parameters:
id ?: string | number | symbol
: constitutes the identifier (name, number or symbol) of theSyncReducerProvider
,AsyncReducerProvider
,SyncMapperProvider
orAsyncMapperProvider
being accessed.
returns:
- the
dispatcher
of the respective Reducer/Mapper Provider.
import { useReducerDispatcher } from 'react-reducer-provider'
import React from 'react'
export default function SomeComponent2() {
const dispatch = useReducerDispatcher('someNamedReducer')
return (
<button onClick={() => dispatch('ACTION2')}>
Go down!
</button>
)
}
useReducerState
/useMapperState
useReducerState(id)
useMapperState(id)
parameters:
id ?: string | number | symbol
: constitutes the identifier (name, number or symbol) of theSyncReducerProvider
,AsyncReducerProvider
,SyncMapperProvider
orAsyncMapperProvider
being accessed.
returns:
- the
state
of the respective Reducer/Mapper Provider.
import { useReducerState } from 'react-reducer-provider'
import React from 'react'
export default function SomeComponentN() {
const currentState = useReducerState('someNamedReducer')
return (
<div>
Current:{currentState}
</div>
)
}
Error
When the associated Reducer Provider can not be found, i.e. the id
trying to be used by any react-reducer-provider
hook is not defined, the the following error may appear:
TypeError: Cannot read property '_context' of undefined
Check the id
of the defined Reducer Providers, and use a valid one.
Synchronous Consumption
Dispatcher
-
when accessing the Reducer Provider, the
dispatcher
will be also a synchronous function:function dispatch<ACTION>(action: ACTION): void
e.g.:
export default function SomeComponent2() {
const dispatch = useReducerDispatcher('someNamedReducer')
return (
<button onClick={() => dispatch('ACTION2')}>
Go down!
</button>
)
}
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 Consumption
Dispatcher
-
when accessing the Reducer Provider, the
dispatcher
will be also a asynchronous function:async function dispatch<ACTION>(action: ACTION): Promise<void>
e.g.:
export default function SomeComponent2() {
const dispatch = useReducerDispatcher('someNamedReducer')
return (
<button onClick={(async () => dispatch('ACTION2').then(someProcess())}>
Go down!
</button>
)
}
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.
More Documentation
AsyncReducerProvider
·SyncReducerProvider
·AsyncMapperProvider
·SyncMapperProvider
.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.