Я использую хук useReducer
с Context для создания хранилища состояний Redux, поддерживающего промежуточное ПО.
const Provider = (props: any) => {
const [state, dispatch] = React.useReducer(reducer, {
title: 'Default title',
count: 0,
});
const actionDispatcher = makeActionDispatcher(
dispatch,
applyMiddleware(state, thunkMiddleware, callApiMiddleware, logger),
);
return (
<Context.Provider value={{ ...state, ...actionDispatcher }}>
{props.children}
</Context.Provider>
);
};
Обратите внимание, что я передаю state
applyMiddleware
:
const applyMiddleware = (state: {}, ...middlewares: Function[]) =>
function dispatcher(dispatch: Function) {
const middlewareAPI = {
state,
dispatch: (...args) => dispatch(...args),
};
const chain = middlewares.map((middleware) => {
return middleware(middlewareAPI);
});
return compose(...chain)(dispatch);
};
Это работает, но в конце концов я хочу иметь возможность работать с асинхронными действиями, поэтому в идеале у меня должно быть что-то вроде redux-thunk
:
function thunkMiddleware(store: Store) {
return (next: Function) => (action: any) => {
typeof action === 'function' ? action(next, store.getState) : next(action);
};
}
Учитывая, что промежуточное ПО thunk будет действовать наасинхронные действия, в идеале мы могли бы пропустить функцию для извлечения текущего состояния при необходимости - getState
- вместо того, чтобы принудительно использовать состояние в том виде, в каком оно существовало на момент применения промежуточного программного обеспечения, что может быть устаревшим.
Обычно я передаю что-то вроде этого:
const getState = () => React.useReducer(reducer, {
title: 'Default title',
count: 0,
})[0];
Но если я передаю это промежуточному программному обеспечению для вызова, я получаю ошибку, указывающую, что я могу вызывать только перехватчики из функций React .
Я что-то неправильно понимаю?Не правильно ли я заворачиваю голову вокруг крючков?
ОБНОВЛЕНИЕ: добавление запрашиваемой makeActionDispatcher
реализации
export const makeActionDispatcher = (
dispatch: React.Dispatch<any> | undefined,
enhancer?: Function,
): ActionDispatcher => {
const actionDispatcher: { [key: string]: (...args: any) => void } = {};
Object.keys(actionCreators).forEach((key) => {
const creator = actionCreators[key];
actionDispatcher[key] = (...args: any) => {
if (!dispatch) {
throw new Error('ActionDispatcher has not been initialized!');
}
const action = creator(...args);
if (enhancer) {
const enhancedDispatch = enhancer(dispatch);
enhancedDispatch(action);
} else {
dispatch(action);
}
};
});
return actionDispatcher as ActionDispatcher;
};