reactjs - Anpassad Hook med generiska typer TypeScript


Jag har ett problem med att skapa gränssnitt till min egna hook usePagination. Jag behöver hjälp att skapa denna hook som generisk, eftersom gränssnittet User inte relaterar till de andra gränssnitten just nu. dataEntries är en array av användare med id, firstName och lastName. ElementsOnPage är satt till 50 som standard.

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

Jag har försökt att göra något sådant här:

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
}

utan snarare skulle jag vilja hämta något liknande detta med hjälp av generiska typer:

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

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

Svar #1

Du har nästan rätt. Du måste bara göra ditt PaginationState-gränssnitt generiskt:

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

Och skicka sedan T till PaginationState i din usePagination-funktion.

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

Nu kan usePagination härleda dess generiska typ och föra den vidare till PaginationState<T>

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

Lekplats