Migrations
Migration to 5.0.0
Basically when consuming Tagged Providers, old states
and dispatchers
are not available anymore, only a get
function to get any provider:
When using hooks
Use useTaggedAny
instead of useTaggedAnyState
or useTaggedAnyDispatcher
.
useTaggedAnyState
anduseTaggedAnyDispatcher
were removed.- types
TaggedStates
andTaggedDispatchers
were removed. TaggedProviderGetter
type was added.useTaggedAny
changed the return value to aTaggedProviderGetter
value.TaggedProviderValue
definition changed.
Change from:
function Component1(): ReactElement {
const [ states, dispatchers ]: TaggedProviderValue<'Tag1' | 'TagN', TestState1 | TestStateN> = useTaggedAny<'Tag1' | 'TagN', TestState1 | TestStateN>('someNamedReducer')
return (
<button onClick={(): void => dispatchers.get('Tag1')('ACTION1', 'somevalue1', {})}>
Child{states.get('TagN').lastAction}
</button>
)
}
function Component2(): ReactElement {
const states: TaggedStates<'Tag1' | 'TagN', TestState1 | TestStateN> = useTaggedAnyState<'Tag1' | 'TagN', TestState1 | TestStateN>('someNamedReducer')
const dispatchers: TaggedDispatchers<'Tag1' | 'TagN'> = useTaggedAnyDispatcher<'Tag1' | 'TagN'>('someNamedReducer')
return (
<button onClick={(): void => dispatchers.get('Tag1')('ACTION1', 'somevalue1', {})}>
Child{states.get('TagN').lastAction}
</button>
)
}
to:
interface SyncTaggedProviderGetter extends TaggedProviderGetter<'Tag1' | 'TagN', TestState1 | TestStateN> {}
function Component1(): ReactElement {
const providers: SyncTaggedProviderGetter = useTaggedAny<'Tag1' | 'TagN', TestState1 | TestStateN>('someNamedReducer')
return (
<button onClick={(): void => providers.get('Tag1').dispatch('ACTION1', 'somevalue1', {})}>
Child{providers.get('TagN').state.lastAction}
</button>
)
}
function Component2(): ReactElement {
const providers: SyncTaggedProviderGetter = useTaggedAny<'Tag1' | 'TagN', TestState1 | TestStateN>('someNamedReducer')
return (
<button onClick={(): void => providers.get('Tag1')[1]('ACTION1', 'somevalue1', {})}>
Child{providers.get('TagN')[0].lastAction}
</button>
)
}
When using HOC
Use injectTaggedAny
instead of injectTaggedAnyState
or injectTaggedAnyDispatcher
.
injectTaggedAnyState
andinjectTaggedAnyDispatcher
were removed.- types
TaggedStates
andTaggedDispatchers
were removed. TaggedProviderGetter
type was added.injectTaggedAny
changed the injected value to aTaggedProviderGetter
value.TaggedProviderValue
definition changed.
Change from:
interface ComponentProps { someProp: string }
interface ComponentState { someState: number }
interface InnerComponent1Props extends ComponentProps { tagged: TaggedProviderValue<'Tag1' | 'TagN', TestState1 | TestStateN> }
class InnerComponent1 extends React.Component<InnerComponent1Props, ComponentState> {
render() {
const [ states, dispatchers ]: TaggedProviderValue<'Tag1' | 'TagN', TestState1 | TestStateN> = this.props.tagged
return (
<button onClick={(): void => dispatchers.get('Tag1')('ACTION1')}>
Child{states.get('Tag1').lastAction}
</button>
)
}
}
const Component1 = injectTaggedAny<{ tagged: any }, ComponentProps>(InnerComponent1, 'tagged', 'someNamedMapper')
interface InnerComponent2Props extends ComponentProps { states: TaggedStates<'Tag1' | 'TagN', TestState1 | TestStateN> }
class InnerComponent2 extends React.Component<InnerComponent2Props, ComponentState> {
render() {
const theStates: TaggedStates<'Tag1' | 'TagN', TestState1 | TestStateN> = this.props.states
return (
<button>
Child{theStates.get('Tag1').lastAction}
</button>
)
}
}
const Component2 = injectTaggedAnyState<{ states: any }, ComponentProps>(InnerComponent2, 'states', 'someNamedMapper')
interface InnerComponent3Props extends ComponentProps { dispatchers: TaggedDispatchers<'Tag1' | 'TagN'> }
class InnerComponent3 extends React.Component<InnerComponent3Props, ComponentState> {
render() {
const theDispatchers: TaggedDispatchers<'Tag1' | 'TagN'> = this.props.dispatchers
return (
<button onClick={(): void => theDispatchers.get('Tag1')('ACTION1')}>
Children
</button>
)
}
}
const Component3 = injectTaggedAnyDispatcher<{ dispatchers: any }, ComponentProps>(InnerComponent3, 'dispatchers', 'someNamedMapper')
to:
interface SyncTaggedProviderGetter extends TaggedProviderGetter<'Tag1' | 'TagN', TestState1 | TestStateN> {}
interface ComponentProps { someProp: string }
interface ComponentState { someState: number }
interface InnerComponent1Props extends ComponentProps { tagged: SyncTaggedProviderGetter }
class InnerComponent1 extends React.Component<InnerComponent1Props, ComponentState> {
render() {
const theProviders: TestSyncTaggedProviderGetter = this.props.tagged
return (
<button onClick={(): void => theProviders.get('Tag1').dispatch('ACTION1')}>
Child{theProviders.get('Tag1').state.lastAction}
</button>
)
}
}
const Component1 = injectTaggedAny<{ tagged: SyncTaggedProviderGetter }, ComponentProps>(InnerComponent1, 'tagged', 'someNamedMapper')
interface InnerComponent2Props extends ComponentProps { providers: SyncTaggedProviderGetter }
class Component2 extends React.Component<InnerComponent2Props, ComponentState> {
render() {
const theProviders: SyncTaggedProviderGetter = this.props.providers
return (
<button>
Child{theProviders.get('Tag1').state.lastAction}
</button>
)
}
}
const Component2 = injectTaggedAny<{ providers: SyncTaggedProviderGetter }, ComponentProps>(InnerComponent2, 'providers', 'someNamedMapper')
interface InnerComponent3Props extends ComponentProps { providers: SyncTaggedProviderGetter }
class Component3 extends React.Component<InnerComponent3Props, ComponentState> {
render() {
const theProviders: SyncTaggedProviderGetter = this.props.providers
return (
<button onClick={(): void => theProviders.get('Tag1').dispatch('ACTION1')}>
Children
</button>
)
}
}
const Component3 = injectTaggedAny<{ providers: SyncTaggedProviderGetter }, ComponentProps>(InnerComponent3, 'providers', 'someNamedMapper')
Migration from react-named-reducer
to react-reducer-provider
1 . Change package dependency:
package.json
:
-
from:
"react-named-reducer": "2.0.1"
-
to:
"react-reducer-provider": "5.0.0"
2 . Change imports:
-
from:
import .. from 'react-named-reducer'
-
to:
import .. from 'react-reducer-provider'
Main source - Reducer Component Definition
3 . Change the “old” NamedReducer
to SyncReducerProvider
:
3 . a. Change import:
-
from:
import { NamedReducer } from 'react-named-reducer'
-
to:
import { SyncReducerProvider } from 'react-reducer-provider'
3 . b. Change Component:
-
from:
NamedReducer
-
to:
SyncReducerProvider
e.g.:
from:
import React from "react";
import { NamedReducer } from "react-named-reducer";
const initialState = 0;
function reduce(prevState, action) {
switch (action) {
case "ACTION1":
return prevState + 1;
case "ACTION2":
return prevState - 1;
default:
return prevState;
}
}
function SomeNamedReducer({ children }) {
return (
<NamedReducer
name="someNamedReducer"
reducer={reduce}
initialState={initialState}
>
{children}
</NamedReducer>
);
}
export { SomeNamedReducer };
to:
import React from "react";
import { SyncReducerProvider } from "react-reducer-provider";
const initialState = 0;
function reduce(prevState, action) {
switch (action) {
case "ACTION1":
return prevState + 1;
case "ACTION2":
return prevState - 1;
default:
return prevState;
}
}
function SomeNamedReducer({ children }) {
return (
<SyncReducerProvider
id="someNamedReducer"
reducer={reduce}
initialState={initialState}
>
{children}
</SomeNamedReducer>
);
}
export { SomeNamedReducer };
Typings
-
from:
NamedReducerProps
-
to:
SyncReducerProps
Main source - Reducer Consumption
4 . Change uses of “old” useNamedReducer
to useReducer
hook:
4 . a. Change import:
-
from:
import { useNamedReducer } from 'react-named-reducer'
-
to:
import { useReducer } from 'react-reducer-provider'
4 . b. Change hook:
-
from:
const { state, dispatch } = useNamedReducer("someNamedReducer")
-
to:
const [ state, dispatch ] = useReducer("someNamedReducer")
e.g.:
from:
import { useNamedReducer } from 'react-named-reducer';
import React from "react";
export default function SomeComponent1() {
const { state, dispatch } = useNamedReducer("someNamedReducer")
return <button onClick={() => dispatch("ACTION1")}>Go up (from {state})!</button>;
}
to:
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>
);
}
if context was used, i.e.
const [state, dispatch] = useContext(useNamedReducerContext('someNamedReducer'))
, just change it toconst [ state, dispatch ] = useReducer("someNamedReducer")
.
Typings
-
from:
NamedReducerInterface
-
to:
ProviderValue
e.g.:
from:
const { state, dispatch }: NamedReducerInterface<State, Action> = useNamedReducer("someNamedReducer")
to:
const [ state, dispatch ]: ProviderValue<State, Action> = useReducer("someNamedReducer");
Prefer Types in function approach, typings.
Test Source
With traditional & sensational Jasmine:
from:
import * as ReactNamedReducer from 'react-named-reducer'
..
mockState = {}
mockDispatcher = jasmine.createSpy('dispatcher')
spyOn(ReactNamedReducer, 'useNamedReducer')
.and
.returnValue({
state: mockState,
dispatch: mockDispatcher
})
to:
import * as ReducerProviderModule from 'react-reducer-provider'
..
mockState = {}
mockDispatcher = jasmine.createSpy('dispatcher')
spyOn(ReducerProviderModule, 'useReducer')
.and
.returnValue([
mockState,
mockDispatcher
])
With Jest:
from:
mockState = {}
mockDispatcher = jest.fn()
jest.mock('react-named-reducer', () => ({
useNamedReducer: () => ({
state: mockState,
dispatch: mockDispatcher
})
}))
to:
mockState = {}
mockDispatcher = jest.fn()
jest.mock('react-reducer-provider', () => ({
useReducer: () => [
mockState,
mockDispatcher
]
}))