@ajna/pagination

中文文档
1.4.19发布于 2022/06/10MITTypeScriptCommonJS近 30 天下载 1.2万

Table of Contents

原始使用文档
文档目录27 节
  1. Table of Contents
  2. Version
  3. Installation
  4. npm
  5. Yarn
  6. Demo with all options applied
  7. Check it out in this Sandbox
  8. Components
  9. Pagination
  10. PaginationContainer
  11. PaginationPageGroup
  12. PaginationPrevious
  13. PaginationNext
  14. PaginationPage
  15. PaginationSeparator
  16. Hooks
  17. usePagination
  18. Usage
  19. Minimal
  20. Styling
  21. Disabling
  22. Page size
  23. Limits
  24. Separator
  25. Offset
  26. Total
  27. Full usage example

@ajna/pagination

Table of Contents

Version

npm version


Installation

npm

npm i @ajna/pagination

Yarn

yarn add @ajna/pagination

Demo with all options applied

Check it out in this Sandbox


Components


Pagination

PropDescriptionTypeDefaultRequired
pagesCountThe total number of pagesnumberyes
currentPageThe page which is currently being selectednumberyes
onPageChangeOn change handler which returns the last selected page(currentPage: number) => voidyes
isDisabledDenotates if all items on the pagination are disabled or notbooleanfalseno

PaginationContainer

It's a Flex component, so any FlexProps are accepted


PaginationPageGroup

It's a Stack component, so any StackProps are accepted


PaginationPrevious

It's a Button component, so any ButtonProps are accepted


PaginationNext

It's a Button component, so any ButtonProps are accepted


PaginationPage

It's a Button component, so any ButtonProps are accepted


PaginationSeparator

It's a Button component, so any ButtonProps are accepted


Hooks

usePagination


Options

PropDescriptionTypeDefaultRequired
initialStateInitial states for pagination valuesInitialStateyes
totalThe total amount of items from the endpoint you are consumingnumberundefinedno
limitsThe limits cut the amount of pages to showLimitsundefinedno
pagesCountIf the amount of pages is manually set, it will take precedencenumberundefinedno

Returned values

PropDescriptionTypeDefault
offsetOffset value generatednumber0
pagesThe array of pages to rendernumber[][]
pagesCountThe total amount of pagesnumber0
currentPageThe page which is currently being selectednumber
pageSizeThe amount of items per pagenumberundefined
isDisabledDenotates if all items on the pagination are disabled or notbooleanfalse
setPageSizeA setter for the isDisabled valueDispatch<SetStateAction>
setIsDisabledA setter for the isDisabled valueDispatch<SetStateAction>
setCurrentPageA setter for the currentPage valueDispatch<SetStateAction>

Usage


Minimal

This is the bare minimum set up you need to get it up and working

import React, { FC, ChangeEvent, useEffect, useState } from "react";
import { ChakraProvider } from "@chakra-ui/react";
import {
  Pagination,
  usePagination,
  PaginationNext,
  PaginationPage,
  PaginationPrevious,
  PaginationContainer,
  PaginationPageGroup,
} from "@ajna/pagination";

const Minimal: FC = () => {
  const {
    currentPage,
    setCurrentPage,
    pagesCount,
    pages
  } = usePagination({
    pagesCount: 12,
    initialState: { currentPage: 1 },
  });

  return (
    <ChakraProvider>
      <Pagination
        pagesCount={pagesCount}
        currentPage={currentPage}
        onPageChange={setCurrentPage}
      >
        <PaginationContainer>
          <PaginationPrevious>Previous</PaginationPrevious>
          <PaginationPageGroup>
            {pages.map((page: number) => (
              <PaginationPage 
                key={`pagination_page_${page}`} 
                page={page} 
              />
            ))}
          </PaginationPageGroup>
          <PaginationNext>Next</PaginationNext>
        </PaginationContainer>
      </Pagination>
    </ChakraProvider>
  );
};

export default Demo;

Styling

The _curent prop will contain the props for the page which is currently selected All other props will apply to every other page

<PaginationPage
  w={7}
  bg="red.300"
  fontSize="sm"
  _hover={{
    bg: "green.300"
  }}
  _current={{
    w: 7,
    bg: "green.300"
    fontSize: "sm"
    _hover: {
      bg: "blue.300"
    },
  }}
>

<PaginationPrevious
  bg="blue.500"
  w="20rem"
  //...any button prop
>
  Previous
</PaginationPrevious>

<PaginationNext
  w={7}
  bg="red.300"
  fontSize="sm"
  //...any button prop
>
  Next
</PaginationNext>

<PaginationContainer
  bg="blue.500"
  w="full"
  //...any flex prop
>
  ...
</PaginationContainer>

<PaginationPageGroup
  bg="blue.500"
  w="full"
  //...any stack prop
>
  ...
</PaginationPageGroup>

Disabling

It's provided a commodity disable prop to disable/enable all your pagination components at once

const { isDisabled, setIsDisabled } = usePagination({
  initialState: { isDisabled: false }
});

const handleDisableClick = () => {
  return setIsDisabled((oldState) => !oldState);
};

<Pagination
  isDisabled={isDisabled}
>

Page size

It's provided a commodity page size setter and getter

const { pageSize, setPageSize } = usePagination({
  initialState: { pageSize: 5 },
});

const handlePageSizeChange = (event: ChangeEvent<HTMLSelectElement>) => {
  const pageSize = Number(event.target.value);

  setPageSize(pageSize);
};

Limits

You can trim the ammount of pages you show by passing both limits at the same time You need to pass them both, otherwise no limits will be applied

const { pages } = usePagination({
  limits: {
    outer: outerLimit,
    inner: innerLimit,
  },
});

Separator

Additionaly, you can customize the separator component used when limits are defined

<PaginationPageGroup separator={<PaginationSeparator _hover={{ bg: 'purple.500' }} bg='teal.500'>}>
  {pages.map((page: number) => (
    <PaginationPage key={`pagination_page_${page}`} page={page} />
  ))}
</PaginationPageGroup>

Offset

It's possible that the API for the pagination you are consuming works with an offset One it's calculated and provided for you using the pageSize and currentPage values

This is calculated with the next formula:

[currentPage * pageSize - pageSize]

currentPage === 1 && pageSize === 5 // offset = 0;
currentPage === 2 && pageSize === 5 // offset = 5;
currentPage === 3 && pageSize === 5 // offset = 10;
const { offset, pageSize } = usePagination({
  initialState: { pageSize: 5 },
});

fetchUsingOffset(pageSize, offset).then((data) => {
  // use data
});

Total

Keep in mind that if you know the total amount of items of the requested endpoint, which is not a strange thing to be returned, you can use that to generate the pages for you

const { pages, pagesCount } = usePaginator({
  total: 4021,
  initialState: { pageSize: 5 }
});

<Pagination
  pagesCount={pagesCount}
>

<PaginationPageGroup>
  {pages.map((page: number) => (
    <PaginationPage key={`pagination_page_${page}`} page={page} />
  ))}
</PaginationPageGroup>

Full usage example

In this example you can see all the possible features provided by the library being applied to show 10 pokemons names, with the ability to play with the page size and disable state

import React, { FC, ChangeEvent, useEffect, useState } from "react";
import { Grid, Center, Select, Text, Button, Stack } from "@chakra-ui/react";
import {
  Pagination,
  usePagination,
  PaginationPage,
  PaginationNext,
  PaginationPrevious,
  PaginationPageGroup,
  PaginationContainer,
  PaginationSeparator,
} from "@ajna/pagination";

const fetchPokemons = async (
  pageSize: number,
  offset: number
): Promise<any> => {
  return await fetch(
    `https://pokeapi.co/api/v2/pokemon?limit=${pageSize}&offset=${offset}`
  ).then(async (res) => await res.json());
};

const Full: FC = () => {
  // states
  const [pokemonsTotal, setPokemonsTotal] = useState<number | undefined>(
    undefined
  );
  const [pokemons, setPokemons] = useState<any[]>([]);

  // constants
  const outerLimit = 2;
  const innerLimit = 2;

  // pagination hook
  const {
    pages,
    pagesCount,
    offset,
    currentPage,
    setCurrentPage,
    setIsDisabled,
    isDisabled,
    pageSize,
    setPageSize,
  } = usePagination({
    total: pokemonsTotal,
    limits: {
      outer: outerLimit,
      inner: innerLimit,
    },
    initialState: {
      pageSize: 5,
      isDisabled: false,
      currentPage: 1,
    },
  });

  // effects
  useEffect(() => {
    fetchPokemons(pageSize, offset)
      .then((pokemons) => {
        setPokemonsTotal(pokemons.count);
        setPokemons(pokemons.results);
      })
      .catch((error) => console.error("App =>", error));
  }, [currentPage, pageSize, offset]);

  // handlers
  const handlePageChange = (nextPage: number): void => {
    // -> request new data using the page number
    setCurrentPage(nextPage);
    console.log("request new data with ->", nextPage);
  };

  const handlePageSizeChange = (
    event: ChangeEvent<HTMLSelectElement>
  ): void => {
    const pageSize = Number(event.target.value);

    setPageSize(pageSize);
  };

  const handleDisableClick = (): void => {
    setIsDisabled((oldState) => !oldState);
  };

  return (
    <Stack>
      <Pagination
        pagesCount={pagesCount}
        currentPage={currentPage}
        isDisabled={isDisabled}
        onPageChange={handlePageChange}
      >
        <PaginationContainer
          align="center"
          justify="space-between"
          p={4}
          w="full"
        >
          <PaginationPrevious
            _hover={{
              bg: "yellow.400",
            }}
            bg="yellow.300"
            isDisabled
            onClick={() => console.warn("I'm clicking the previous")}
          >
            <Text>Previous</Text>
          </PaginationPrevious>
          <PaginationPageGroup
            isInline
            align="center"
            separator={
              <PaginationSeparator
                isDisabled
                onClick={() => console.warn("I'm clicking the separator")}
                bg="blue.300"
                fontSize="sm"
                w={7}
                jumpSize={11}
              />
            }
          >
            {pages.map((page: number) => (
              <PaginationPage
                w={7}
                bg="red.300"
                key={`pagination_page_${page}`}
                page={page}
                onClick={() => console.warn("Im clicking the page")}
                fontSize="sm"
                _hover={{
                  bg: "green.300",
                }}
                _current={{
                  bg: "green.300",
                  fontSize: "sm",
                  w: 7,
                }}
              />
            ))}
          </PaginationPageGroup>
          <PaginationNext
            _hover={{
              bg: "yellow.400",
            }}
            bg="yellow.300"
            onClick={() => console.warn("I'm clicking the next")}
          >
            <Text>Next</Text>
          </PaginationNext>
        </PaginationContainer>
      </Pagination>
      <Center w="full">
        <Button
          _hover={{
            bg: "purple.400",
          }}
          bg="purple.300"
          onClick={handleDisableClick}
        >
          Disable ON / OFF
        </Button>
        <Select ml={3} onChange={handlePageSizeChange} w={40}>
          <option value="10">10</option>
          <option value="25">25</option>
          <option value="50">50</option>
        </Select>
      </Center>
      <Grid
        gap={3}
        mt={20}
        px={20}
        templateColumns="repeat(5, 1fr)"
        templateRows="repeat(2, 1fr)"
      >
        {pokemons?.map(({ name }) => (
          <Center key={name} bg="green.100" p={4}>
            <Text>{name}</Text>
          </Center>
        ))}
      </Grid>
    </Stack>
  );
};

export default Full;

版本与发布记录

@ajna/pagination 共发布 21 个版本,首次发布于 2021/07/18;过去 12 个月发布了 0 个版本。

版本发布日期距今
1.4.19latest2022/06/104 年前
1.4.182022/06/104 年前
1.4.172022/04/014 年前
1.4.162022/04/014 年前
1.4.142022/03/084 年前
1.4.132021/08/105 年前

关于 @ajna/pagination 的常见问题

@ajna/pagination 是什么?

Table of Contents

如何安装 @ajna/pagination?

在项目目录运行 npm install @ajna/pagination,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:@chakra-ui/react(^2.2.1)、@emotion/react(^11.9.0)、@emotion/styled(^11.8.1)、framer-motion(^6.3.11)、react(^18.1.0)、react-dom(^18.1.0)、react-scripts(5.0.1)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@ajna/pagination 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@ajna/pagination 支持 ESM 还是 CommonJS?

以 CommonJS 形式发布,可以直接 require();在 ES Module 项目中也可以用 import 引入(Node.js 会把 module.exports 作为默认导出)。

@ajna/pagination 可以商用吗?

@ajna/pagination 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@ajna/pagination 的下载量有多少?

根据 npm 官方下载统计,@ajna/pagination 在 2026/10/05 – 2026/11/03 这 30 天内被下载 11,813 次,日均约 394 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@ajna/pagination 还在维护吗?

最新版本 1.4.19 发布于 2022/06/10(4 年前);至今共发布 21 个版本,其中过去 12 个月发布了 0 个;首次发布于 2021/07/18。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。