TS - многоразовый перехватчик запроса API - тип не может быть назначен типу IUseApiHook
Что я пытаюсь сделать?
Я хочу создать функцию, которая может выполнять любой тип запроса API для внешнего приложения. В принципе, я хочу пофантазировать.
Проблема?
Я нахожусь над головой, и мне нужен еще один глаз, чтобы взглянуть на мой сломанный подход.
Вот ошибка, которую я получаю из приведенного ниже кода:
Type '<T>(options: TApiHookOptions) => { data: Accessor<T | null>; error: Accessor<Error | null>; loading: Accessor<boolean>; request: void; }' is not assignable to type 'IUseApiHook'.
Call signature return types '{ data: Accessor<unknown>; error: Accessor<Error | null>; loading: Accessor<boolean>; request: void; }' and 'TApiHook<T>' are incompatible.
The types of 'data' are incompatible between these types.
Type 'Accessor<unknown>' is not assignable to type 'T'.
'T' could be instantiated with an arbitrary type which could be unrelated to 'Accessor<unknown>'.ts(2322)
Код (все здесь):
import { createEffect, createSignal } from "solid-js";
import axios from "axios";
export type TApiResponse<T> = {
data: T;
error: Error | null;
};
export type TApiHook<T> = {
data: T | null;
error: Error | null;
loading: boolean;
request: () => void;
};
export type TApiHookOptions = {
url: string;
method?: "get" | "post" | "put" | "delete";
data?: any;
};
export interface IUseApiHook {
<T>(options: TApiHookOptions): TApiHook<T>;
}
export const useApiHook: IUseApiHook = <T>(options: TApiHookOptions) => {
const [data, setData] = createSignal<T | null>(null);
const [error, setError] = createSignal<Error | null>(null);
const [loading, setLoading] = createSignal(false);
const request = createEffect(() => {
setLoading(true);
axios({
url: options.url,
method: options.method || "get",
data: options.data,
})
.then((response) => {
setData(response.data);
setError(null);
})
.catch((error) => {
setError(error);
})
.finally(() => {
setLoading(false);
});
});
return {
data,
error,
loading,
request,
};
};
1 ответ
Я не знаю, но глядя на документы и типы, первое возвращаемое значение — это функция, которая возвращает значение с сохранением состояния.
Это означает, что вы хотите сделать это:
return {
data: data(),
error: error(),
loading: loading(),
request,
};
Но есть еще проблема с
request
. Вы набрали его как функцию, но
createEffect
возвращается
void
. Я не думаю, что вам нужен эффект здесь вообще (эффект — это функция, запускаемая после любого рендера, в котором изменились зависимости). Это обратный вызов (то, что вы запускаете, когда пользователь выполняет действие), а не эффект. В простой реакции вы бы использовали
useCallback()
запомнить эту функцию. Но я думаю, просто запомнить его?
const request = createMemo(() => {
setLoading(true);
axios({
url: options.url,
method: options.method || "get",
data: options.data,
})
.then((response) => {
setData(response.data);
setError(null);
})
.catch((error) => {
setError(error);
})
.finally(() => {
setLoading(false);
});
}, options);
Хотя я не уверен на 100%, что
solid-js
рекомендовал бы здесь, или если требуется мемоизация (это требуется в простой реакции, если эта функция будет использоваться в качестве зависимостей для любого другого хука).