Files
react-table/src/plugin-hooks/usePagination.js
T
Andros Rosa LlopandTanner Linsley 2ecdfbd24e [Fix] defaultGetResetPageDeps should listen to data, not rows (#1658)
Related to: https://github.com/tannerlinsley/react-table/issues/1657

Discussion: https://spectrum.chat/react-table/general/v7-maximum-update-depth-exceeded-usegroupby-useexpanded-with-usepagination~2c25e2b8-7a61-4c32-84b3-87db458701c2

Thanks to @iamjon for identifying usePagination was the culprit.
I then checked the last changes made to it, and noticed it was previously listening to data and now it listened to rows (which I believe is a new reference on each render), causing infinite loop on one of its effects.

I tested this change on my project and everything seems ok now.
2019-11-25 12:24:20 -07:00

164 lines
3.6 KiB
JavaScript
Executable File

import React from 'react'
//
import { addActions, actions } from '../actions'
import { defaultState } from '../hooks/useTable'
import { ensurePluginOrder, safeUseLayoutEffect, expandRows } from '../utils'
defaultState.pageSize = 10
defaultState.pageIndex = 0
addActions('pageChange', 'pageSizeChange')
export const usePagination = hooks => {
hooks.useMain.push(useMain)
}
usePagination.pluginName = 'usePagination'
const defaultGetResetPageDeps = ({
data,
manualPagination,
state: { filters, groupBy, sortBy },
}) => [manualPagination ? null : data, filters, groupBy, sortBy]
function useMain(instance) {
const {
rows,
manualPagination,
getResetPageDeps = defaultGetResetPageDeps,
manualExpandedKey = 'expanded',
debug,
plugins,
pageCount: userPageCount,
paginateExpandedRows = true,
expandSubRows = true,
state: { pageSize, pageIndex, expanded },
setState,
} = instance
ensurePluginOrder(
plugins,
['useFilters', 'useGroupBy', 'useSortBy', 'useExpanded'],
'usePagination',
[]
)
// Bypass any effects from firing when this changes
const isMountedRef = React.useRef()
safeUseLayoutEffect(() => {
if (isMountedRef.current) {
setState(
old => ({
...old,
pageIndex: 0,
}),
actions.pageChange
)
}
isMountedRef.current = true
}, [setState, ...(getResetPageDeps ? getResetPageDeps(instance) : [])])
const pageCount = manualPagination
? userPageCount
: Math.ceil(rows.length / pageSize)
const pageOptions = React.useMemo(
() => (pageCount > 0 ? [...new Array(pageCount)].map((d, i) => i) : []),
[pageCount]
)
const page = React.useMemo(() => {
let page
if (manualPagination) {
page = rows
} else {
if (process.env.NODE_ENV === 'development' && debug)
console.info('getPage')
const pageStart = pageSize * pageIndex
const pageEnd = pageStart + pageSize
page = rows.slice(pageStart, pageEnd)
}
if (paginateExpandedRows) {
return page
}
return expandRows(page, { manualExpandedKey, expanded, expandSubRows })
}, [
debug,
expandSubRows,
expanded,
manualExpandedKey,
manualPagination,
pageIndex,
pageSize,
paginateExpandedRows,
rows,
])
const canPreviousPage = pageIndex > 0
const canNextPage = pageCount === -1 || pageIndex < pageCount - 1
const gotoPage = React.useCallback(
updater => {
if (process.env.NODE_ENV === 'development' && debug)
console.info('gotoPage')
return setState(old => {
const newPageIndex =
typeof updater === 'function' ? updater(old.pageIndex) : updater
if (newPageIndex < 0 || newPageIndex > pageCount - 1) {
return old
}
return {
...old,
pageIndex: newPageIndex,
}
}, actions.pageChange)
},
[debug, pageCount, setState]
)
const previousPage = React.useCallback(() => {
return gotoPage(old => old - 1)
}, [gotoPage])
const nextPage = React.useCallback(() => {
return gotoPage(old => old + 1)
}, [gotoPage])
const setPageSize = React.useCallback(
pageSize => {
setState(old => {
const topRowIndex = old.pageSize * old.pageIndex
const pageIndex = Math.floor(topRowIndex / pageSize)
return {
...old,
pageIndex,
pageSize,
}
}, actions.pageSizeChange)
},
[setState]
)
return {
...instance,
pageOptions,
pageCount,
page,
canPreviousPage,
canNextPage,
gotoPage,
previousPage,
nextPage,
setPageSize,
pageIndex,
pageSize,
}
}