前言
记录一下公司 下拉框封装的 接口hook。主要是支持
- 初始化或者指定状态下请求接口
- 防抖搜索
- 支持不同类型的接口(get、post)
代码
主体 hook
tsx
import { IObj, IOption, TRecord } from "@/utils/interface";
import { to } from "@/utils/tools";
import { useMount } from "@quarkunlimit/react-hooks";
import { debounce } from "lodash";
import { useEffect, useRef, useState } from "react";
import {
IUseMountFetchDataNewProps,
IUseMountFetchDataResult,
} from "./interface";
/**
* 初始化请求下拉框接口
* @param props
* @returns
*/
export const useSearchSelectFetchNew = (
props: IUseMountFetchDataNewProps
): IUseMountFetchDataResult => {
const {
fetchDataApi,
request,
searchParamKey,
transformOptions,
refreshFetch,
initFetch = true,
needSetExtarData = false,
} = props;
const [data, setData] = useState<IOption[]>([]);
const isMount = useRef<boolean>(false);
const originData = useRef<IOption[]>([]);
const fetchData = async (otherRequest?: TRecord) => {
let newRequst: IObj = {}
newRequst = {
page: 1,
size: 100,
...request,
...otherRequest
}
const [err, res] = await to(
(() => {
return fetchDataApi(newRequst);
})()
);
if (!(err || !res)) {
const data = transformOptions(res);
setData(data);
if (!isMount.current) {
originData.current = data;
isMount.current = true;
}
}
};
const onSearch = debounce((value: string) => {
if (value.trim()) {
fetchData({
[searchParamKey]: value,
});
} else {
setData(originData.current);
}
}, 500);
useEffect(() => {
if (refreshFetch) {
fetchData();
}
}, [refreshFetch]);
useMount(() => {
if (initFetch) {
fetchData();
}
});
const setExtarData = (list: IOption[]) => {
const newData: IOption[] = [];
const idSet = new Set<string>();
for (let item of data) {
newData.push(item);
idSet.add(item.value);
}
for (let item of list) {
if (typeof item !== "object") {
continue;
}
if (idSet.has(item?.value)) {
continue;
}
idSet.add(item.value);
newData.push(item);
}
setData(newData);
};
return {
options: data,
onSearch,
onFocus: () => fetchData(),
...(needSetExtarData ? { setExtarData } : {}),
};
};
类型定义
ts
import { SelectProps } from "antd";
export interface IOption {
label: string;
value: string;
[key: string]: any;
}
export interface IUseMountFetchDataNewProps {
/**@param 接口Api */
fetchDataApi: (...arg: any) => Promise<IApiData>;
/**@param 初始化时接口额外参数 */
request?: TRecord & { enableFlag?: boolean; dataScopeEnableFlag?: boolean };
/**@param 搜索时的key */
searchParamKey: string;
/**@function 转换数据源为options */
transformOptions: (res: IApiData) => IOption[];
/**@param 满足某种条件时加载数据,使用时请将 initFetch 设置为 false */
refreshFetch?: boolean;
/**@param 是否挂载时默认加载数据 */
initFetch?: boolean;
/** @param 是否需要setExtarData */
needSetExtarData?: boolean;
}
export interface IUseMountFetchDataResult extends SelectProps {
/** @param 下拉框选项 */
options: IOption[];
/** @function 下拉框搜索 */
onSearch: (value: string) => void;
/** @function 手动添加额外的数据源 */
setExtarData?: (list: IOption[]) => void;
}
使用
tsx
/** @function 获取字典值集合 */
export const sys_dict_value = (params?: IReqSysDictValueDictValue) => {
return Service.get("/api/business/v1/sys-dict-value/dict-value", {
params,
}) as Promise<IResDetail<IResSysDictValueDictValue[]>>;
};
export interface IReqSysDictValueDictValue {
/** @param 字典编码 */
dictCode?: string;
/** @param 字典编码集合 */
dictCodeList?: string;
/** @param 字典名称 */
dictName?: string;
/** @param 字典值 */
dictValue?: string;
/** @param 备注 */
memo?: string;
}
export interface IResSysDictValueDictValue {
dictCode: string;
dictName: string;
dictValue: string;
enableFlag: boolean;
id: string;
memo: string;
color: string;
sortNum: number;
}
const TXDiplomaRadio = function TXDiplomaRadio_({
initFetch = true,
refreshFetch = false,
extraReq = {},
...rest
}: ITXDiplomaRadioProps) {
const { options } = useSearchSelectFetchNew({
fetchDataApi: sys_dict_value(你的接口,返回promise),
request: {
dictCode: "diploma",
...extraReq,
},
initFetch,
refreshFetch,
searchParamKey: "dictName",
transformOptions: (res) => {
return res?.data?.map((x: IResSysDictValueDictValue) => ({
label: x.dictName,
value: x.dictValue,
}));
},
});
return <Radio.Group options={options} {...rest} />;
};
export default TXDiplomaRadio;