简体   繁体   中英

Custom Hook with Generic Types TypeScript

I have a problem with making interfaces to my custom hook usePagination. I need a help to create this hook as generic, because the interface User does'nt relate to rest of interfaces in this moment. dataEntries are array of users with id, firstName and lastName. ElementsOnPage is set to 50 as default.

function usePagination(dataEntries,elementsOnPage = 50) {
  const [actualPageIdx, setActualPageIdx] = useState(1)
  const lastPageIdx = Math.ceil(dataEntries.length / elementsOnPage)
  const [isBusy, setIsBusy] = useState(false)
  const timeoutRef = useRef<any>(null)


  useEffect(() => {
    setIsBusy(true)
    if (timeoutRef.current) {
      clearTimeout(timeoutRef.current)
    }
    timeoutRef.current = setTimeout(() => {
      setIsBusy(false)
    }, 333)
  }, [actualPageIdx])

  const entriesOnSelectedPage = () => {
    const firstEntry = (actualPageIdx - 1) * elementsOnPage
    const lastEntry = firstEntry + elementsOnPage
    console.log(dataEntries.slice(firstEntry, lastEntry))
    return dataEntries.slice(firstEntry, lastEntry)
  }

  const goToFirstPage = useCallback(() => {
    setActualPageIdx(1)
  }, [])

  const goToLastPage = () => {
    setActualPageIdx(lastPageIdx)
  }

  const goToPage = (page: number) => {
    setActualPageIdx(page)
  }

  const goToPrevPage = () => {
    setActualPageIdx((actualPageIdx) => (actualPageIdx === 1 ? actualPageIdx : actualPageIdx - 1))
  }

  const goToNextPage = () => {
    setActualPageIdx((actualPageIdx) =>
      actualPageIdx === lastPageIdx ? actualPageIdx : actualPageIdx + 1
    )
  }
 
  return [
    { actualPageIdx, 
      lastPageIdx, 
      entriesOnSelectedPage, 
      isBusy },
    {
      goToFirstPage,
      goToPrevPage,
      goToPage,
      goToNextPage,
      goToLastPage,
    },
  ]
}

I have tried to do sth like this:

interface User {
  id: number
  firstName: string
  lastName: string
}

interface PaginationState {
  lastPageIdx: number
  actualPageIdx: number
  entriesOnSelectedPage: () => User[]
  isBusy: boolean
}

interface PaginationActions {
  goToFirstPage: () => void
  goToPrevPage: () => void
  goToNextPage: () => void
  goToLastPage: () => void
  goToPage: (number: number) => void
}

but rather I would like to retrieve sth like this using generic types:

function usePagination<T>(dataEntries: T[], elementsOnPage = 50): [PaginationState, PaginationActions] {

  return [
    { actualPageIdx, 
      lastPageIdx, 
      entriesOnSelectedPage, 
      isBusy },
    {
      goToFirstPage,
      goToPrevPage,
      goToPage,
      goToNextPage,
      goToLastPage,
    },
  ]
}

You almost have it. You just have to make your PaginationState interface generic:

interface PaginationState<T> {
  lastPageIdx: number
  actualPageIdx: number
  entriesOnSelectedPage: () => T[]
  isBusy: boolean
}

And then pass T to PaginationState in your usePagination function.

function usePagination<T>(
  dataEntries: T[],
  elementsOnPage = 50
): [PaginationState<T>, PaginationActions] {
  //...
}

Now usePagination can infer it's generic type and pass it along through to PaginationState<T>

const users: User[] = []
const [state, action] = usePagination(users) // state has type PaginationState<User>

Playground

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM