Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 29 additions & 73 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,41 @@
import React from 'react';
import './App.css';
import { getNumbers } from './utils';
import { useState } from 'react';
import { Pagination } from './components/Pagination';

// eslint-disable-next-line @typescript-eslint/no-unused-vars
const items = getNumbers(1, 42).map(n => `Item ${n}`);

export const App: React.FC = () => {
const [perPage, setPerPage] = useState(Number('5'));
const [currentPage, setCurrentPage] = useState(1);
const lastItems = perPage * currentPage;
const firstItem = lastItems - perPage;

const newItems = items.slice(firstItem, lastItems);

return (
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant .map(n => n) - this creates a new array with the same values. Use getNumbers(1, pageCount) directly, or use .map with a meaningful transformation if needed.

<div className="container">
<h1>Items with Pagination</h1>

<p className="lead" data-cy="info">
Page 1 (items 1 - 5 of 42)
Page {currentPage} (items {firstItem + 1} -{' '}
Comment on lines 22 to +23
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hardcoded 42 should be replaced with total prop to properly display the actual total count when it changes.

{lastItems > 42 ? 42 : lastItems} of 42)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The onClick handler on <li> always calls onPageChange, even when disabled. According to requirement #5, the callback should only be triggered if the page was actually changed. Currently, clicking the disabled prev button still calls onPageChange(currentPage - 1) which evaluates to onPageChange(0) when on page 1. Move the page change logic to the <a> onClick handler or add guards to prevent calling onPageChange when disabled.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hardcoded 42 should use total prop for consistency with the actual data length.

</p>

<div className="form-group row">
<div className="col-3 col-sm-2 col-xl-1">
<select
data-cy="perPageSelector"
id="perPageSelector"
className="form-control">
value={perPage}
onChange={event => {
setPerPage(Number(event.target.value));
setCurrentPage(1);
}}
className="form-control"
>
<option value="3">3</option>
<option value="5">5</option>
<option value="10">10</option>
Expand All @@ -32,78 +48,18 @@ export const App: React.FC = () => {
</label>
</div>

{/* Move this markup to Pagination */}
<ul className="pagination">
<li className="page-item disabled">
<a
data-cy="prevLink"
className="page-link"
href="#prev"
aria-disabled="true">
«
</a>
</li>
<li className="page-item active">
<a data-cy="pageLink" className="page-link" href="#1">
1
</a>
</li>
<li className="page-item">
<a data-cy="pageLink" className="page-link" href="#2">
2
</a>
</li>
<li className="page-item">
<a data-cy="pageLink" className="page-link" href="#3">
3
</a>
</li>
<li className="page-item">
<a data-cy="pageLink" className="page-link" href="#4">
4
</a>
</li>
<li className="page-item">
<a data-cy="pageLink" className="page-link" href="#5">
5
</a>
</li>
<li className="page-item">
<a data-cy="pageLink" className="page-link" href="#6">
6
</a>
</li>
<li className="page-item">
<a data-cy="pageLink" className="page-link" href="#7">
7
</a>
</li>
<li className="page-item">
<a data-cy="pageLink" className="page-link" href="#8">
8
</a>
</li>
<li className="page-item">
<a data-cy="pageLink" className="page-link" href="#9">
9
</a>
</li>
<li className="page-item">
<a
data-cy="nextLink"
className="page-link"
href="#next"
aria-disabled="false">
»
</a>
</li>
</ul>
<Pagination
total={items.length}
perPage={perPage}
currentPage={currentPage}
Comment on lines 50 to +54
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue as prev button - onPageChange is called on every click, including when disabled. Clicking the disabled next button on the last page still triggers the callback with the same page number.

onPageChange={setCurrentPage}
/>
<ul>
<li data-cy="item">Item 1</li>
<li data-cy="item">Item 2</li>
<li data-cy="item">Item 3</li>
<li data-cy="item">Item 4</li>
<li data-cy="item">Item 5</li>
{newItems.map(item => (
<li data-cy="item" key={item}>
{item}
</li>
))}
</ul>
</div>
);
Expand Down
68 changes: 67 additions & 1 deletion src/components/Pagination/Pagination.tsx
Original file line number Diff line number Diff line change
@@ -1 +1,67 @@
export const Pagination = () => {};
import cn from 'classnames';
import React from 'react';
import { getNumbers } from '../../utils';

type Props = {
total: number;
perPage: number;
currentPage: number;
onPageChange: (page: number) => void;
};
export const Pagination: React.FC<Props> = ({
total,
perPage,
currentPage = 1,
onPageChange,
}) => {
const pageCount = Math.ceil(total / perPage);
const listItems = getNumbers(1, pageCount).map(n => n);

return (
<ul className="pagination">
<li
className={cn('page-item', { disabled: currentPage === 1 })}
onClick={() => onPageChange(currentPage <= 1 ? 1 : currentPage - 1)}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The onClick handler on <li> always calls onPageChange even when on the first page. Requirement #5 states callback should be triggered only if page was changed. When currentPage === 1, clicking previous should not call onPageChange at all.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pagination info display logic is incorrect. Using lastItems > 42 ? 42 : lastItems caps the upper bound on ALL pages, but it should only cap on the LAST page. For example, with perPage=20 on page 2: current code shows 'items 21 - 42 of 42' but should show 'items 21 - 40 of 42'.

>
<a
data-cy="prevLink"
className="page-link"
href="#prev"
aria-disabled={currentPage === 1}
>
«
</a>
Comment on lines +28 to +40
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The onClick handler is on the <li> element instead of <a>. This means clicking on disabled items still triggers the callback. Move onClick to the <a> element and add a condition to prevent calling onPageChange when already on page 1.

</li>
{listItems.map(count => (
<li
key={count}
className={cn('page-item ', { active: currentPage === count })}
>
<a
data-cy="pageLink"
className="page-link"
onClick={() => onPageChange(count)}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This calls onPageChange directly without checking if the page actually changed. For consistency with the prev/next buttons (which use handlePageChange), this should also use handlePageChange(count) to ensure the callback is only triggered when the page actually changes (requirement #5).

href={`#${count}`}
>
{count}
</a>
</li>
))}
<li
className={cn('page-item', { disabled: currentPage === pageCount })}
onClick={() =>
onPageChange(currentPage >= pageCount ? pageCount : currentPage + 1)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The onClick handler always calls onPageChange even when already on the last page. Requirement #5 states callback should be triggered only if page was changed. When currentPage === pageCount, clicking next should not call onPageChange at all.

}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The onClick handler is on the <li> element instead of <a>. This means clicking on disabled items still triggers the callback. Move onClick to the <a> element and add a condition to prevent calling onPageChange when already on the last page.

>
<a
data-cy="nextLink"
className="page-link"
href="#next"
aria-disabled={currentPage === pageCount}
>
»
</a>
</li>
</ul>
);
};
139 changes: 139 additions & 0 deletions src/components/sdsds.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
перейти до: пошук пакетів вмісту вхід

Професіонал
Команди
Ціноутворення
Документація
нпм
Пошук пакетів
Пошук
реагувати на сторінки
Піктограма DefinitelyTyped, яка вказує на те, що цей пакет містить оголошення TypeScript, надані окремим пакетом @types/react-paginate
8.3.0 • Громадськість • Опублікованорік тому
реагувати на сторінки
НПМ Стан збірки

Компонент ReactJS для рендерингу пагінації.

Встановивши цей компонент і написавши лише трохи CSS, ви можете отримати ось що: Примітка: Вам слід написати власний CSS, щоб отримати цей інтерфейс користувача. Цей пакет не надає жодного CSS.

Демонстрація пагінації 2

або

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The onPageChange callback is invoked even when clicking on the current page or already-disabled navigation. The task requires that onPageChange should be triggered only if page was changed. Add a conditional check: e.g., const prevPage = currentPage - 1; if (prevPage >= 1) onPageChange(prevPage);

Демонстрація пагінації 1

Встановлення
Встановити react-paginateза допомогою npm :

npm install react-paginate --save
Використання
імпортувати React , { useEffect , useState } з 'react' ;
імпортувати ReactDOM з 'react-dom' ;
імпортувати ReactPaginate з 'react-paginate' ;

// Приклади елементів для імітації отримання з інших ресурсів.
const items = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 ] ;

функція Елементи ( { currentItems } ) {
return (
< >
{ currentItems &&
currentItems.map ( ( item ) = > ( <div> <h3> Елемент № { item } </h3> </div> ) ) } < / > ) ; }​​​​​​​








function PaginatedItems ( { itemsPerPage } ) {
// Тут ми використовуємо зміщення елементів; ми також можемо використовувати зміщення сторінок
// відповідно до API або даних, з якими ви працюєте.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar issue: onPageChange is called on every click, including when already on the last page. The callback should only fire if the page number actually changes. Add a condition to check if currentPage < pageCount before calling the callback.

const [ itemOffset , setItemOffset ] = useState ( 0 ) ;

// Імітація отримання елементів з інших ресурсів. // (Це можуть бути елементи з props; або елементи
, завантажені в локальному стані
// з кінцевої точки API за допомогою useEffect та useState)
const endOffset = itemOffset + itemsPerPage ;
console.log ( ` Завантаження елементів з $ { itemOffset } до $ { endOffset } ` ) ; const currentItems = items.slice ( itemOffset , endOffset ) ; const pageCount = Math.ceil ( items.length / itemsPerPage ) ;




// Викликати , коли користувач клацає , щоб запросити іншу сторінку. const handlePageClick = ( event ) = > {
const newOffset = ( event.selected * itemsPerPage ) % items.length ; console.log ( `Користувач запросив номер сторінки $ { event.selected } , який дорівнює зсуву ${ newOffset } ` ) ; setItemOffset ( newOffset ) ; } ;






повернути (
< >
< Елементи currentItems = { currentItems } />
< ReactPaginate
breakLabel = "..."
nextLabel = "наступний >"
onPageChange = { handlePageClick }
pageRangeDisplayed = { 5 }
pageCount = { pageCount }
previousLabel = "< попередній"
renderOnZeroPageCount = { null }
/>
</ >
) ;
}


// Додайте < div id="container"> до вашого HTML , щоб побачити відображення компонента. ReactDOM.render ( < PaginatedItems itemsPerPage = { 4 } /> , document.getElementById ( 'container' ) ) ;


Перевірте це на CodePen .

Ви також можете прочитати код demo/js/demo.js , щоб швидко зрозуміти, як працювати react-paginateзі списком об'єктів.

Нарешті, є ця демонстрація CodePen з функціями отримання зразків коду (за допомогою GitHub API) та двома синхронізованими віджетами пагінації.

Реквізит
Ім'я Тип Опис
pageCount Number Обов’язково. Загальна кількість сторінок.
pageRangeDisplayed Number Діапазон відображених сторінок.
marginPagesDisplayed Number Кількість сторінок для відображення з полями.
previousLabel Node Мітка для previousкнопки.
nextLabel Node Мітка для nextкнопки.
breakLabel Node Мітка для трикрапки.
breakAriaLabels Shape Мітки Aria для елементів еліпса (за замовчуванням { forward: 'Jump forward', backward: 'Jump backward' }).
breakClassName String Назва класу на тезі liелемента з трьома крапками.
breakLinkClassName String Назва класу на тезі aелемента з трьома крапками.
onPageChange Function Метод, який викликається під час зміни сторінки. Надає поточний об'єкт сторінки як аргумент.
onClick Function Зворотний виклик для будь-якого кліку на компоненті. Надає інформацію про частину, на яку було зроблено клацання (наприклад, isNextдля наступного елемента керування), наступну очікувану сторінку nextSelectedPageтощо. Може повертати значення false, щоб запобігти будь-якій зміні сторінки, або номер для перевизначення сторінки для переходу.
onPageActive Function Метод, який викликається при кліці на активній сторінці. Надає об'єкт активної сторінки як аргумент.
initialPage Number Початкова сторінка вибрана в неконтрольованому режимі . Не використовувати з forcePageодночасно.
forcePage Number Щоб перезаписати вибрану сторінку батьківською властивістю. Використовуйте це, якщо хочете керувати сторінкою зі стану вашої програми.
disableInitialCallback boolean Вимкнути onPageChangeзворотний виклик із початковою сторінкою. За замовчуванням:false
containerClassName String Назва класу контейнера пагінації.
className String Те саме, що containerClassName. Для використання зі стилізованими компонентами та іншими CSS-in-JS.
pageClassName String Назва класу в тезі liкожного елемента сторінки.
pageLinkClassName String Назва класу в тезі aкожного елемента сторінки.
pageLabelBuilder Function Функція для встановлення тексту на посиланнях сторінок. За замовчуванням(page) => page
activeClassName String Назва класу для активної сторінки. Вона об'єднана з базовим класом pageClassName.
activeLinkClassName String Назва класу для активного тегу a. Вона об'єднана з базовим класом pageLinkClassName.
previousClassName String Назва класу на тезі liкнопки previous.
nextClassName String Назва класу на тезі liкнопки next.
previousLinkClassName String Назва класу на тезі aкнопки previous.
nextLinkClassName String Назва класу на тезі aкнопки next.
disabledClassName String Назва класу для disabled previousта nextbuttons.
disabledLinkClassName String Назва класу aдля тегу disabled previousта nextbuttons.
hrefBuilder Function Метод викликається для генерації hrefзначення атрибута тегу aкожного елемента сторінки.
hrefAllControls Bool За замовчуванням hrefBuilderдодається hrefлише до активних елементів керування. Встановіть цю властивість trueтак , щоб hrefвони генерувалися на всіх елементах керування ( див. ).
extraAriaContext String ЗАСТАРІЛО: Додатковий контекст для додавання до aria-labelатрибута HTML.
ariaLabelBuilder Function Метод викликається для генерації aria-labelзначення атрибута для кожного посилання на сторінку
eventListener String Подія, яку потрібно прослухати перед зміною вибраної сторінки. Значення за замовчуванням: onClick.
renderOnZeroPageCount Function Функція рендерингу, що викликається when pageCountдорівнює нулю. Нехай кнопки «Попередній» / «Наступний» відображаються за замовчуванням ( undefined). Нічого не відображати when nullпередбачено.
prevRel String Властивість relтегу aдля елемента керування попередньою сторінкою. Значення за замовчуванням prev. Встановіть значення , nullщоб вимкнути.
nextRel String Властивість relтегу aдля елемента керування наступною сторінкою. Значення за замовчуванням next. Встановіть значення , nullщоб вимкнути.
prevPageRel String Властивість relтегу aбезпосередньо перед вибраною сторінкою. Значення за замовчуванням prev. Встановіть значення , nullщоб вимкнути.
selectedPageRel String Властивість relтегу aдля вибраної сторінки. Значення за замовчуванням canonical. Встановіть значення , nullщоб вимкнути.
nextPageRel String Властивість relтегу aодразу після вибраної сторінки. Значення за замовчуванням next. Встановіть значення , nullщоб вимкнути.
Loading