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/useMapperDispatcherand/oruseReducerState/useMapperState, Be Aware that they useReact.useContextand quote: ‘A component calling useContext will always re-render when the context value changes’, in this case whenstatechanges, therefore when usinguseReducerDispatcher/useMapperDispatcheralthough it not depends “directly” onstatethe component will be re-render whenstatechanges. Final words, useSyncMapperProviderand/orAsyncMapperProvider,SyncReducerProviderand/orAsyncReducerProvidereverywhere is required and useuseReducer/useMapper,useReducerDispatcher/useMapperDispatcherand/oruseReducerState/useMapperStatewisely (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,SyncMapperProviderorAsyncMapperProviderbeing 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 extensibleException.
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*Dispatcheroruse*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,SyncMapperProviderorAsyncMapperProviderbeing accessed.
returns:
- the
dispatcherof 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,SyncMapperProviderorAsyncMapperProviderbeing accessed.
returns:
- the
stateof 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
dispatcherwill be also a synchronous function:function dispatch<ACTION>(action: ACTION): voide.g.:
export default function SomeComponent2() {
const dispatch = useReducerDispatcher('someNamedReducer')
return (
<button onClick={() => dispatch('ACTION2')}>
Go down!
</button>
)
}
An
SyncReducerProviderexample can be checked on line at gmullerb-react-reducer-provider codesandbox:
AnSyncMapperProviderexample can be checked on line at gmullerb-react-mapper-provider codesandbox:
Asynchronous Consumption
Dispatcher
-
when accessing the Reducer Provider, the
dispatcherwill 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
dispatchis resolved is an indication that the state was change, but not of any required re-rendering being done.
AnAsyncReducerProvidercan be checked on line at gmullerb-react-reducer-provider codesandbox:
AnAsyncMapperProviderexample can be checked on line at gmullerb-react-mapper-provider-async codesandbox:
AlthoughAsyncReducerProvidercan 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.