#javascript #reactjs #typescript #react-redux #redux-middleware
#javascript #reactjs #typescript #реагировать-redux #redux-промежуточное программное обеспечение
Вопрос:
Согласно определению Redux в typescript, эти интерфейсы должны быть реализованы для создания промежуточного программного обеспечения:
/* middleware */
export interface MiddlewareAPI<D extends Dispatch = Dispatch, S = any> {
dispatch: D
getState(): S
}
/**
* A middleware is a higher-order function that composes a dispatch function
* to return a new dispatch function. It often turns async actions into
* actions.
*
* Middleware is composable using function composition. It is useful for
* logging actions, performing side effects like routing, or turning an
* asynchronous API call into a series of synchronous actions.
*
* @template DispatchExt Extra Dispatch signature added by this middleware.
* @template S The type of the state supported by this middleware.
* @template D The type of Dispatch of the store where this middleware is
* installed.
*/
export interface Middleware<
DispatchExt = {},
S = any,
D extends Dispatch = Dispatch
> {
(api: MiddlewareAPI<D, S>): (
next: Dispatch<AnyAction>
) => (action: any) => any
}
Я пробовал это:
import { Middleware, Dispatch, AnyAction, MiddlewareAPI } from 'redux';
import { AppState } from 'AppState';
class MiddlewareBase implements Middleware<{}, AppState, Dispatch<AnyAction>> {
constructor() {
return (api: MiddlewareAPI<Dispatch<AnyAction>, AppState>) =>
(next: Dispatch<AnyAction>) =>
(action: AnyAction) =>
{
// TODO: Do something before calling the next middleware.
return next(action);
};
}
}
export default MiddlewareBase;
Но компилятор жалуется на это:
Type 'MiddlewareBase' provides no match for the signature '(api: MiddlewareAPI<Dispatch<AnyAction>, AppState>): (next: Dispatch<AnyAction>) => (action: any) => any'
Обновить:
Это должен быть класс, а не функция. Я создал базовый класс, чтобы я мог наследовать их позже.
Комментарии:
1. У вас возникнут проблемы, если вам придется использовать class. Мой совет, просто не делайте этого. Я не вижу конкретной причины, по которой вы должны. Какой-то другой механизм вместо наследования?
2. Расскажите нам, как вы собираетесь использовать этот базовый класс.
3. Если вы возвращаете функцию из конструктора вместо обычного
this
объекта, тогда нет смысла использовать класс. Эта функция не будет иметь доступа к прототипу класса.
Ответ №1:
Вы можете посмотреть на мой код. Должно быть что-то вроде этого:
import { MiddlewareAPI, Dispatch, Middleware, AnyAction } from "redux";
const callAPIMiddleware: Middleware<Dispatch> = ({
dispatch
}: MiddlewareAPI) => next => (action: AnyAction | CallApiAction) => {
if (!action.meta || !action.meta.callApi) {
return next(action);
}
const { successAction, errorAction, url, params } = action.payload;
return fetchFn(url, params)
.then(res => res.json())
.then(res =>
dispatch({
type: successAction,
payload: res
})
)
.catch(res =>
dispatch({
type: errorAction,
payload: res
})
);
};
Комментарии:
1. Привет, спасибо за помощь, однако мне нужно, чтобы это был класс, поскольку он наследуется другими классами. Я должен был добавить это к вопросу, я думаю
2. Я думаю, вы не сможете этого сделать. Потому что redux принимает функции в качестве промежуточных программ. Вы, конечно, можете создать класс с методом, который реализует некоторую логику, но это все равно будет функция. Мой совет: используйте композицию функций вместо наследования. reactjs.org/docs/composition-vs-inheritance.html
3. Если вы добавляете второй аргумент в
Middleware
с типом состояния вашего приложения и используетеgetState
(который доступен рядомdispatch
), то вам не нуженMiddlewareAPI
здесь, потому что это отбрасываетgetState
возвращаемый тип. Просто опустите этоMiddlewareAPI
, иgetState
будет возвращен второй общий аргументMiddleware
.
Ответ №2:
Во-первых, такого понятия, как «класс промежуточного программного обеспечения redux», не существует. Итак, ответ на ваш практический вопрос прост: вы не можете.
Redux Middleware
— это функциональный интерфейс, а не интерфейс класса. Хотя в javascript вы могли бы принудительно возвращать функцию (вместо this
объекта) из конструктора класса, вы не должны этого делать с typescript. Компилятор, вероятно, будет жаловаться на это, потому что это антипаттерн, а синтаксис класса не предназначен для такого хакерского использования. Даже если он не жалуется, я вижу абсолютно нулевую выгоду от такого взлома.
Итак, вы хотите реализовать что-то «наследуемое». Вам не обязательно использовать синтаксис класса. По иронии судьбы, вы могли бы использовать шаблон промежуточного программного обеспечения. Примените базовое промежуточное программное обеспечение до того, как промежуточное программное обеспечение даст вам эффект наследования.
Теперь я не знаю, что вы собираетесь делать, поэтому не буду приводить бессмысленные примеры. Если вы потрудитесь объяснить, что вы пытаетесь сделать, я рассмотрю это.