Skip to content

Instantly share code, notes, and snippets.

@rohailtaha
Last active December 20, 2021 07:41
Show Gist options
  • Save rohailtaha/dfefa4593a0a448fd8b1f722cbd01c53 to your computer and use it in GitHub Desktop.
Save rohailtaha/dfefa4593a0a448fd8b1f722cbd01c53 to your computer and use it in GitHub Desktop.
React | Redux Pagination
import { useDispatch } from 'react-redux';
import { set_current_page } from '../../../../../actions/pagination/pagination-actions';
export default function NextPageButton({ currentPage, disabled }) {
const dispatch = useDispatch();
return (
<li>
<button
className={`page${
disabled ? '' : ' page--clickable'
} btn btn-secondary btn-sm d-flex px-1 mx-0 btn--change-page`}
onClick={() => dispatch(set_current_page(currentPage + 1))}
disabled={disabled}
style={{ cursor: `${disabled ? 'auto' : 'pointer'}` }}
>
<span className='material-icons'>arrow_forward</span>
</button>
</li>
);
}
import { useDispatch } from 'react-redux';
import { set_current_page } from '../../../../actions/pagination/pagination-actions';
export default function Page({ pageNumber, active }) {
const dispatch = useDispatch();
return (
<li>
<button
className={`page page--clickable${
active ? ' active-page' : ''
} btn btn-sm btn-secondary mx-0`}
onClick={() => dispatch(set_current_page(pageNumber))}
>
{pageNumber}
</button>
</li>
);
}
import PreviousPageButton from './navigation-buttons/PreviousPageButton';
import NextPageButton from './navigation-buttons/NextPageButton';
import Page from './Page';
export default function PagesList({ currentPage, totalPages }) {
const endPagesNotReached = () => currentPage + 2 <= totalPages;
const getPageNumbers = () => {
const pageNumbers = [];
if (endPagesNotReached()) {
for (
let pageNumber = currentPage;
pageNumber <= currentPage + 2;
pageNumber++
) {
pageNumbers.push(pageNumber);
}
} else {
for (
let pageNumber = totalPages - 2;
pageNumber <= totalPages;
pageNumber++
) {
if (pageNumber > 0) pageNumbers.push(pageNumber);
}
}
return pageNumbers;
};
const disablePreviousPageButton = () => currentPage === 1;
const disableNextPageButton = () => currentPage === totalPages;
return (
<ul className='pages__list d-flex justify-content-center align-items-center ps-0 mb-1'>
<PreviousPageButton
disabled={disablePreviousPageButton()}
currentPage={currentPage}
/>
{getPageNumbers().map(pageNumber => (
<Page
key={pageNumber}
pageNumber={pageNumber}
active={pageNumber === currentPage}
/>
))}
<NextPageButton
disabled={disableNextPageButton()}
currentPage={currentPage}
/>
</ul>
);
}
import actionTypes from '../action-types';
export const set_current_page = pageNumber => ({
type: actionTypes.SET_CURRENT_PAGE,
payload: pageNumber,
});
export const display_all_items_on_single_page =
totalItems => async dispatch => {
return dispatch(set_items_per_page(totalItems));
};
export const set_items_per_page = itemsPerPage => ({
type: actionTypes.SET_ITEMS_PER_PAGE,
payload: itemsPerPage,
});
export const reset_pagination = () => ({
type: actionTypes.RESET_PAGINATION,
});
import actionTypes from '../../actions/action-types';
import { defaultRowsCountPerPage } from '../../utils/util_structures';
const initialState = {
itemsPerPage: defaultRowsCountPerPage,
currentPage: 1,
};
export default function paginationReducer(state = initialState, action) {
switch (action.type) {
case actionTypes.SET_CURRENT_PAGE:
return {
...state,
currentPage: action.payload,
};
case actionTypes.SET_ITEMS_PER_PAGE:
return {
...state,
itemsPerPage: action.payload,
};
case actionTypes.RESET_PAGINATION:
return initialState;
default:
return state;
}
}
import { Fragment } from 'react';
import { useSelector } from 'react-redux';
import PagesList from './pages-list/PagesList';
export default function Paginaton({ totalItems }) {
const [{ itemsPerPage, currentPage }] = useSelector(state => [
state.pagination,
]);
const getTotalPages = () => Math.ceil(totalItems / itemsPerPage);
const initialItemForCurrentPage = () => (currentPage - 1) * itemsPerPage + 1;
const lastItemForCurrentPage = () => {
return currentPage === getTotalPages()
? totalItems
: currentPage * itemsPerPage;
};
return (
<Fragment>
<div className='d-flex align-items-start mt-3 pagination'>
{getTotalPages() > 1 && (
<div className='pages text-end'>
<PagesList currentPage={currentPage} totalPages={getTotalPages()} />
<p className='pages__info'>
Page {currentPage} of{' '}
<span className='pages__info__total-pages'>
{getTotalPages()}
</span>
</p>
</div>
)}
{totalItems > 0 && (
<p className='total-items-info ms-auto'>
Showing {initialItemForCurrentPage()} to {lastItemForCurrentPage()}{' '}
of {totalItems} entries
</p>
)}
</div>
</Fragment>
);
}
import { useDispatch } from 'react-redux';
import { set_current_page } from '../../../../../actions/pagination/pagination-actions';
export default function PreviousPageButton({ currentPage, disabled }) {
const dispatch = useDispatch();
return (
<li>
<button
className={`page${
disabled ? '' : ' page--clickable'
} btn btn-secondary btn-sm d-flex px-1 mx-0 btn--change-page`}
onClick={() => dispatch(set_current_page(currentPage - 1))}
disabled={disabled}
style={{ cursor: `${disabled ? 'auto' : 'pointer'}` }}
>
<span className='material-icons'>arrow_back</span>
</button>
</li>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment