То, что вы пытаетесь достичь, - это работа в Redux и облегчение bu Redux-thunk middleware .Промежуточное программное обеспечение отсутствует в useReducer
хуке.Так что из коробки это невозможно.
Но вы можете написать свое собственное промежуточное ПО, например, вот так:
import * as React from 'react';
interface FuncState {
prop1: string;
prop2: string;
}
interface FunctAction1 {
type: 'SET_PROP1'; // Action type property has type of 'SET_PROP1'. This is not string, it is type 'SET_PROP1'. The only value type may have is 'SET_PROP1'.
prop1: string;
}
interface FunctAction2 {
type: 'SET_PROP2';
prop2: string;
}
// Here we create union of actions to properly type Reducer
type KnownActions = FunctAction1 | FunctAction2;
const FuncInitState: FuncState = {
prop1: '',
prop2: ''
}
function isFunction(f: any): f is Function {
return typeof f === "function";
}
function useThunkReducer<S, A>(reducer: React.Reducer<S, A>, initialState: React.ReducerState<React.Reducer<S, A>>):
[S, (action: A | ((dispatch: React.Dispatch<A>, state: S) => void)) => void]
{
const [state, dispatch] = React.useReducer(reducer, initialState);
// Essentially this is middleware
const thunkDispatch = (action: A
| ((dispatch: React.Dispatch<A>, state: S) => void)): void => {
if (isFunction(action)) { // This is type guard
return action(dispatch, state);
}
return dispatch(action);
};
return [state, thunkDispatch];
}
const FuncReducer: React.Reducer<FuncState, KnownActions> = (state, action) => {
switch (action.type) {
case 'SET_PROP1':
// action will have type of FunctAction1 as action.type has value 'SET_PROP1'
return { ...state, prop1: action.prop1 }
case 'SET_PROP2':
return { ...state, prop2: action.prop2 }
default:
throw new Error('FuncReducer do not have default');
}
}
const myClickAction = (prop1: string) => (dispatch: React.Dispatch<KnownActions>) => {
console.log(prop1);
dispatch({ type: 'SET_PROP1', prop1: "some value" });
}
const FuncCmp: React.FunctionComponent = () => {
const [state, dispatch] = useThunkReducer(FuncReducer, FuncInitState);
return <div>
FuncCmp
<button onClick={(e) => dispatch(myClickAction("some value"))}>Set prop1</button>
<button onClick={(e) => dispatch({ type: 'SET_PROP2', prop2: "another value" })}>Set prop2</button>
<div>Prop1: {state.prop1}</div>
<div>Prop2: {state.prop2}</div>
</div>;
}
Я добавил комментарии к коду для ясности.
И рабочий пример здесь