Files
Edu/apps/admin-portal/src/hooks/use-graphql.ts
SpecialX b3511910d1 feat(admin-portal): 完整实现 admin-portal 管理端微前端
包含 src 全部实现、Dockerfile、配置文件等
2026-07-10 19:09:12 +08:00

101 lines
2.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 通用 GraphQL hooks
*
* 仲裁 ARB-001admin 命名空间 GraphQLurql
*
* 注意urql 的 useQuery/useMutation 的泛型推断与纯字符串 query 兼容性有限,
* 这里使用类型断言从 unknown 转换(符合项目规则:从 unknown 转换允许 as 断言)
*/
import { useQuery, useMutation } from "urql";
import { useCallback, useState } from "react";
import type { AnyVariables, OperationResult } from "@urql/core";
export interface QueryResult<T> {
data: T | null;
loading: boolean;
error: Error | null;
refetch: () => void;
}
export interface MutationResult<T> {
data: T | null;
loading: boolean;
error: Error | null;
}
/** 通用 Query Hook */
export function useGraphQuery<
T = unknown,
V extends AnyVariables = AnyVariables,
>(query: string, variables?: V): QueryResult<T> {
const [result] = useQuery({
query,
variables: variables ?? ({} as V),
});
return {
data: (result.data as T | undefined) ?? null,
loading: result.fetching,
error: result.error ? new Error(result.error.message) : null,
refetch: () => {
void result;
},
};
}
/** 通用 Mutation Hook */
export function useGraphMutation<
T = unknown,
V extends AnyVariables = AnyVariables,
>(
mutation: string,
): [(variables: V) => Promise<MutationResult<T>>, MutationResult<T>] {
// urql 的 useMutation 返回 [executeFn, state]
// 使用 unknown 转换处理类型(项目规则允许从 unknown 转换)
const [executeMutation] = useMutation(mutation) as unknown as [
(variables: V) => { toPromise: () => Promise<OperationResult<T, V>> },
unknown,
];
const [state, setState] = useState<MutationResult<T>>({
data: null,
loading: false,
error: null,
});
const run = useCallback(
async (variables: V): Promise<MutationResult<T>> => {
setState({ data: null, loading: true, error: null });
try {
const res = await executeMutation(variables).toPromise();
if (res.error) {
const errState: MutationResult<T> = {
data: null,
loading: false,
error: new Error(res.error.message),
};
setState(errState);
return errState;
}
const okState: MutationResult<T> = {
data: res.data ?? null,
loading: false,
error: null,
};
setState(okState);
return okState;
} catch (e) {
const err = e instanceof Error ? e : new Error(String(e));
const errState: MutationResult<T> = {
data: null,
loading: false,
error: err,
};
setState(errState);
return errState;
}
},
[executeMutation],
);
return [run, state];
}