portal-payment-fe/src/components/AsyncSelectPaginate.tsx

74 lines
1.8 KiB
TypeScript

"use client";
import * as React from "react";
import Select from "react-select";
type OptionType = { label: string; value: string };
export default function AsyncSelectPaginate({
loader,
value,
onChange,
...rest
}: any) {
const [options, setOptions] = React.useState<OptionType[]>([]);
const [page, setPage] = React.useState(1);
const [hasMore, setHasMore] = React.useState(false);
const [inputValue, setInputValue] = React.useState("");
const [loading, setLoading] = React.useState(false);
React.useEffect(() => {
let mounted = true;
setLoading(true);
(async () => {
try {
const res = await loader?.(inputValue ?? "", 1);
if (!mounted) return;
const opts = (res && res.options) || [];
setOptions(opts || []);
setHasMore(Boolean(res && res.hasMore));
setPage(1);
} catch (e) {
console.error("AsyncSelectPaginate load error", e);
} finally {
if (mounted) setLoading(false);
}
})();
return () => {
mounted = false;
};
}, [inputValue, loader]);
const loadMore = async () => {
if (loading || !hasMore) return;
setLoading(true);
const next = page + 1;
try {
const res = await loader?.(inputValue ?? "", next);
const opts = (res && res.options) || [];
setOptions((s) => [...s, ...(opts || [])]);
setHasMore(Boolean(res && res.hasMore));
setPage(next);
} catch (e) {
console.error("AsyncSelectPaginate loadMore error", e);
} finally {
setLoading(false);
}
};
return (
<div>
<Select
options={options}
value={value}
onChange={onChange}
onInputChange={(val) => setInputValue(val)}
onMenuScrollToBottom={loadMore}
isLoading={loading}
{...rest}
/>
</div>
);
}