防抖
export const useDebounce = <V>(value: V, delay?: number) => {
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(() => {
const timeout = setTimeout(() => setDebouncedValue(value), delay);
return () => clearTimeout(timeout);
}, [value, delay]);
return debouncedValue;
};
判断组件是否被卸载
export const useMountedRef = () => {
const mountedRef = useRef(false);
useEffect(() => {
mountedRef.current = true;
return () => {
mountedRef.current = false;
};
});
return mountedRef;
};
组件渲染完的钩子在项目中可能用的比较多,也可以先定义好
export const useMount = (callback: () => void) => {
useEffect(() => {
callback();
}, []);
};
操作数组数据
export const useArray = <T>(initialArray: T[]) => {
const [value, setValue] = useState(initialArray);
return {
value,
setValue,
add: (item: T) => setValue([...value, item]),
clear: () => setValue([]),
removeIndex: (index: number) => {
const copy = [...value];
copy.splice(index, 1);
setValue(copy);
},
};
};
获取route query 参数
export const cleanObject = (object: { [key: string]: unknown }) => {
const result = { ...object };
Object.keys(result).forEach((key) => {
const value = result[key];
if (isVoid(value)) {
delete result[key];
}
});
return result;
};
export const subset = <
O extends { [key in string]: unknown },
K extends keyof O
>(
obj: O,
keys: K[]
) => {
const filteredEntries = Object.entries(obj).filter(([key]) =>
keys.includes(key as K)
);
return Object.fromEntries(filteredEntries) as Pick<O, K>;
};
import { URLSearchParamsInit, useSearchParams } from "react-router-dom";
import { useMemo, useState } from "react";
export const useUrlQueryParam = <K extends string>(keys: K[]) => {
const [searchParams, setSearchParam] = useSearchParams();
const [stateKeys] = useState(keys);
return [
useMemo(
() =>
subset(Object.fromEntries(searchParams), stateKeys) as {
[key in K]: string;
},
[searchParams, stateKeys]
),
(params: Partial<{ [key in K]: unknown }>) => {
const o = cleanObject({
...Object.fromEntries(searchParams),
...params,
}) as URLSearchParamsInit;
return setSearchParam(o);
},
] as const;
};
封装fetch 请求
import qs from "qs";
import * as auth from "auth-provider";
import { useAuth } from "context/auth-context";
import { useCallback } from "react";
const apiUrl = process.env.REACT_APP_API_URL;
interface Config extends RequestInit {
token?: string;
data?: object;
}
export const http = async (
endpoint: string,
{ data, token, headers, ...customConfig }: Config = {}
) => {
const config = {
method: "GET",
headers: {
Authorization: token ? `Bearer ${token}` : "",
"Content-Type": data ? "application/json" : "",
},
...customConfig,
};
if (config.method.toUpperCase() === "GET") {
endpoint += `?${qs.stringify(data)}`;
} else {
config.body = JSON.stringify(data || {});
}
return window
.fetch(`${apiUrl}/${endpoint}`, config)
.then(async (response) => {
if (response.status === 401) {
await auth.logout();
window.location.reload();
return Promise.reject({ message: "请重新登录" });
}
const data = await response.json();
if (response.ok) {
return data;
} else {
return Promise.reject(data);
}
});
};