具有通用类型TypeScript的自定义钩子

时间:2020-08-31 16:01:13

标签: reactjs typescript react-hooks

我在与我的自定义钩子usePagination建立接口时遇到问题。我需要帮助来将此钩子创建为通用钩子,因为此时User界面与其余界面无关。 dataEntries是具有id,firstName和lastName的用户数组。 ElementsOnPage默认设置为50。

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,
    },
  ]
}

我试图做这样的事情:

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
}

但是我想使用泛型类型来检索这样的东西:

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

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

1 个答案:

答案 0 :(得分:1)

您几乎拥有它。您只需要使PaginationState界面通用即可:

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

然后在T函数中将PaginationState传递给usePagination

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

现在usePagination可以推断出它的通用类型并将其传递给PaginationState<T>

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

Playground