Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import { Form, Select } from 'antd'
- import { Rule } from 'antd/lib/form'
- import axios from 'axios'
- import { debounce } from 'lodash'
- import { FC, useEffect, useState, CSSProperties, useMemo } from 'react'
- const { Option } = Select
- interface IAsyncSelectProps {
- url: string
- name: string
- label: string
- initialValue: number | string | undefined
- rules?: Rule[] | undefined
- showSearch: boolean
- allowClear: boolean
- style: CSSProperties | undefined
- placeholder: string
- onChange?: (value: any) => void
- size: 'large' | 'middle' | 'small'
- dataMap: (element: any) => JSX.Element
- searchKey: string
- }
- export const AsyncSelect: FC<IAsyncSelectProps> = ({
- url,
- name,
- label,
- initialValue,
- rules,
- showSearch,
- allowClear,
- style,
- placeholder,
- size,
- dataMap,
- searchKey,
- onChange,
- }) => {
- const [page, setPage] = useState(1)
- const [maxPage, setMaxPage] = useState<number>(99)
- const [dataFromFetch, setDataFromFetch] = useState<any[]>([])
- const [searchData, setSearchData] = useState<any[]>([])
- const [loading, setLoading] = useState(false)
- useEffect(() => {
- fetchData()
- }, [])
- useEffect(() => {
- return () => {
- handleDebouncedSearch.cancel()
- }
- })
- const fetchSearchData = async (query: string) => {
- if (!query || query === '') {
- refetchData()
- return
- }
- setLoading(true)
- const {
- data: { data },
- } = await axios.get(`${url}?filters[${searchKey}][$containsi]=${query}`)
- setLoading(false)
- setSearchData(data)
- resetData()
- }
- const fetchInitialData = async () => {
- const {
- data: { data },
- } = await axios.get(`${url}/${initialValue}`)
- return data
- }
- const fetchData = async () => {
- setLoading(true)
- const {
- data: { data, meta },
- } = await axios.get(
- `${url}?pagination[page]=${page}&pagination[pageSize]=10`,
- )
- if (dataFromFetch.length === 0) {
- const initialData = await fetchInitialData()
- if (!data.some((item: any) => item.id === initialValue))
- data.unshift(initialData)
- setDataFromFetch(data)
- }
- if (maxPage === 99) {
- setMaxPage(meta?.pagination?.pageCount)
- }
- setPage(page 1)
- setLoading(false)
- return data.filter((item: any) => item.id !== initialValue)
- }
- const onScroll = async (event: any) => {
- const { target } = event
- if (
- target.scrollTop target.offsetHeight === target.scrollHeight &&
- page <= maxPage &&
- searchData.length === 0
- ) {
- const newData = await fetchData()
- target.scrollTo(0, target.scrollHeight)
- setDataFromFetch(dataFromFetch.concat(newData))
- }
- }
- const handleDebouncedSearch = useMemo(() => {
- return debounce(fetchSearchData, 300)
- }, [])
- const resetData = () => {
- setDataFromFetch([])
- setPage(1)
- }
- const refetchData = () => {
- resetData()
- setSearchData([])
- fetchData()
- }
- return (
- <Form.Item
- name={name}
- label={label}
- initialValue={initialValue}
- rules={rules}
- >
- <Select
- showSearch={showSearch}
- allowClear={allowClear}
- style={style}
- onPopupScroll={onScroll}
- onSearch={handleDebouncedSearch}
- filterOption={false}
- placeholder={placeholder}
- size={size}
- onClear={refetchData}
- onChange={onChange}
- >
- {searchData.length === 0
- ? dataFromFetch.map((item) => dataMap(item))
- : searchData.map((item) => dataMap(item))}
- {loading && <Option>Loading...</Option>}
- </Select>
- </Form.Item>
- )
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement