diff --git a/.size-snapshot.json b/.size-snapshot.json
index 245c1fc..f14036e 100644
--- a/.size-snapshot.json
+++ b/.size-snapshot.json
@@ -1,13 +1,13 @@
{
"dist/index.js": {
- "bundled": 87904,
- "minified": 41988,
- "gzipped": 11252
+ "bundled": 89986,
+ "minified": 42988,
+ "gzipped": 11389
},
"dist/index.es.js": {
- "bundled": 87321,
- "minified": 41480,
- "gzipped": 11132,
+ "bundled": 89403,
+ "minified": 42480,
+ "gzipped": 11267,
"treeshaked": {
"rollup": {
"code": 428,
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5db21b5..9fba370 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,14 @@
## 7.0.0-beta.14
+- Removed
+ - `disablePageResetOnDataChange` option. use the `getResetPageDeps` option now.
+- Added
+ - `getResetPageDeps` option
+ - `getResetFilterDeps` option
+ - `getResetSortByDeps` option
+ - `getResetGroupByDeps` option
+ - `getResetExpandedDeps` option
+
## 7.0.0-beta.13
- Added options
diff --git a/docs/api.md b/docs/api.md
index 4b660b6..989da2b 100644
--- a/docs/api.md
+++ b/docs/api.md
@@ -384,6 +384,11 @@ The following options are supported via the main options object passed to `useTa
- Must be **memoized**
- Allows overriding or adding additional sort types for columns to use. If a column's sort type isn't found on this object, it will default to using the built-in sort types.
- For more information on sort types, see Sorting
+- `getResetSortByDeps: Function(instance) => [...useEffectDependencies]`
+ - Optional
+ - Defaults to `false`
+ - If set, the dependencies returned from this function will be used to determine when the effect to reset the `sortBy` state is fired.
+ - To disable, set to `false`
### Column Options
@@ -487,6 +492,11 @@ The following options are supported via the main options object passed to `useTa
- Must be **memoized**
- Allows overriding or adding additional filter types for columns to use. If a column's filter type isn't found on this object, it will default to using the built-in filter types.
- For more information on filter types, see Filtering
+- `getResetFiltersDeps: Function(instance) => [...useEffectDependencies]`
+ - Optional
+ - Defaults to `false`
+ - If set, the dependencies returned from this function will be used to determine when the effect to reset the `filters` state is fired.
+ - To disable, set to `false`
### Column Options
@@ -696,6 +706,14 @@ The following options are supported via the main options object passed to `useTa
- Defaults to `true`
- If set to `true`, expanded rows are rendered along with normal rows.
- If set to `false`, expanded rows will only be available through their parent row. This could be useful if you are implementing a custom expanded row view.
+- `getResetExpandedDeps: Function(instance) => [...useEffectDependencies]`
+ - Optional
+ - Defaults to resetting the `expanded` state to `[]` when the dependencies below change
+ - ```js
+ const getResetExpandedDeps = ({ data }) => [data]
+ ```
+ - If set, the dependencies returned from this function will be used to determine when the effect to reset the `expanded` state is fired.
+ - To disable, set to `false`
### Instance Properties
@@ -750,10 +768,19 @@ The following options are supported via the main options object passed to `useTa
- `manualPagination: Bool`
- Enables pagination functionality, but does not automatically perform row pagination.
- Turn this on if you wish to implement your own pagination outside of the table (eg. server-side pagination or any other manual pagination technique)
-- `disablePageResetOnDataChange`
- - Defaults to `false`
- - Normally, any changes detected to `rows`, `state.filters`, `state.groupBy`, or `state.sortBy` will trigger the `pageIndex` to be reset to `0`
- - If set to `true`, the `pageIndex` will not be automatically set to `0` when these dependencies change.
+- `getResetPageDeps: Function(instance) => [...useEffectDependencies]`
+ - Optional
+ - Defaults to resetting the `pageIndex` to `0` when the dependencies below change
+ - ```js
+ const getResetPageDeps = ({
+ rows,
+ manualPagination,
+ state: { filters, groupBy, sortBy },
+ }) => [manualPagination ? null : rows, filters, groupBy, sortBy]
+ ```
+ - Note that if `manualPagination` is set to `true`, then the pageIndex should not be reset when `rows` change
+ - If set, the dependencies returned from this function will be used to determine when the effect to reset the `pageIndex` state is fired.
+ - To disable, set to `false`
- `paginateExpandedRows: Bool`
- Optional
- Only applies when using the `useExpanded` plugin hook simultaneously
@@ -833,6 +860,14 @@ The following options are supported via the main options object passed to `useTa
- Optional
- Defaults to `isSelected`
- If this key is found on the **original** data row, and it is true, this row will be manually selected
+- `getResetSelectedRowPathsDeps: Function(instance) => [...useEffectDependencies]`
+ - Optional
+ - Defaults to resetting the `expanded` state to `[]` when the dependencies below change
+ - ```js
+ const getResetSelectedRowPathsDeps = ({ rows }) => [rows]
+ ```
+ - If set, the dependencies returned from this function will be used to determine when the effect to reset the `selectedRowPaths` state is fired.
+ - To disable, set to `false`
### Instance Properties
diff --git a/examples/editable-data/src/App.js b/examples/editable-data/src/App.js
index 087a15b..a9c1c7f 100644
--- a/examples/editable-data/src/App.js
+++ b/examples/editable-data/src/App.js
@@ -76,8 +76,8 @@ const defaultColumn = {
Cell: EditableCell,
}
-// Be sure to pass our updateMyData and the disablePageResetOnDataChange option
-function Table({ columns, data, updateMyData, disablePageResetOnDataChange }) {
+// Be sure to pass our updateMyData and the skipPageReset option
+function Table({ columns, data, updateMyData, skipPageReset }) {
// For this example, we're using pagination to illustrate how to stop
// the current page from resetting when our data changes
// Otherwise, nothing is different here.
@@ -101,7 +101,8 @@ function Table({ columns, data, updateMyData, disablePageResetOnDataChange }) {
columns,
data,
defaultColumn,
- disablePageResetOnDataChange,
+ // use the skipPageReset option to disable page resetting temporarily
+ getResetPageDeps: skipPageReset ? false : undefined,
// updateMyData isn't part of the API, but
// anything we put into these options will
// automatically be available on the instance.
@@ -126,19 +127,16 @@ function Table({ columns, data, updateMyData, disablePageResetOnDataChange }) {
))}
- {page.map(
- (row, i) => {
- prepareRow(row);
- return (
-
- {row.cells.map(cell => {
- return (
- | {cell.render('Cell')} |
- )
- })}
-
- )}
- )}
+ {page.map((row, i) => {
+ prepareRow(row)
+ return (
+
+ {row.cells.map(cell => {
+ return | {cell.render('Cell')} |
+ })}
+
+ )
+ })}
@@ -274,7 +272,7 @@ function App() {
columns={columns}
data={data}
updateMyData={updateMyData}
- disablePageResetOnDataChange={skipPageReset}
+ skipPageReset={skipPageReset}
/>
)
diff --git a/examples/kitchen-sink-controlled/src/App.js b/examples/kitchen-sink-controlled/src/App.js
index 2cecdd9..e8c24b9 100644
--- a/examples/kitchen-sink-controlled/src/App.js
+++ b/examples/kitchen-sink-controlled/src/App.js
@@ -232,8 +232,8 @@ function fuzzyTextFilterFn(rows, id, filterValue) {
// Let the table remove the filter if the string is empty
fuzzyTextFilterFn.autoRemove = val => !val
-// Be sure to pass our updateMyData and the disablePageResetOnDataChange option
-function Table({ columns, data, updateMyData, disablePageResetOnDataChange }) {
+// Be sure to pass our updateMyData and the skipPageReset option
+function Table({ columns, data, updateMyData, skipPageReset }) {
const filterTypes = React.useMemo(
() => ({
// Add a new fuzzyTextFilterFn filter type.
@@ -305,8 +305,8 @@ function Table({ columns, data, updateMyData, disablePageResetOnDataChange }) {
// cell renderer!
updateMyData,
// We also need to pass this so the page doesn't change
- // when we edit the data
- disablePageResetOnDataChange,
+ // when we edit the data, undefined means using the default
+ getResetPageDeps: skipPageReset ? false : undefined,
},
useFilters,
useSortBy,
@@ -350,37 +350,36 @@ function Table({ columns, data, updateMyData, disablePageResetOnDataChange }) {
))}
- {page.map(
- row => {
- prepareRow(row);
- return (
-
- {row.cells.map(cell => {
- return (
- |
- {cell.isGrouped ? (
- // If it's a grouped cell, add an expander and row count
- <>
-
- {row.isExpanded ? '👇' : '👉'}
- {' '}
- {cell.render('Cell', { editable: false })} (
- {row.subRows.length})
- >
- ) : cell.isAggregated ? (
- // If the cell is aggregated, use the Aggregated
- // renderer for cell
- cell.render('Aggregated')
- ) : cell.isRepeatedValue ? null : ( // For cells with repeated values, render null
- // Otherwise, just render the regular cell
- cell.render('Cell', { editable: true })
- )}
- |
- )
- })}
-
- )}
- )}
+ {page.map(row => {
+ prepareRow(row)
+ return (
+
+ {row.cells.map(cell => {
+ return (
+ |
+ {cell.isGrouped ? (
+ // If it's a grouped cell, add an expander and row count
+ <>
+
+ {row.isExpanded ? '👇' : '👉'}
+ {' '}
+ {cell.render('Cell', { editable: false })} (
+ {row.subRows.length})
+ >
+ ) : cell.isAggregated ? (
+ // If the cell is aggregated, use the Aggregated
+ // renderer for cell
+ cell.render('Aggregated')
+ ) : cell.isRepeatedValue ? null : ( // For cells with repeated values, render null
+ // Otherwise, just render the regular cell
+ cell.render('Cell', { editable: true })
+ )}
+ |
+ )
+ })}
+
+ )
+ })}
{/*
@@ -623,7 +622,7 @@ function App() {
columns={columns}
data={data}
updateMyData={updateMyData}
- disablePageResetOnDataChange={skipPageResetRef.current}
+ skipPageReset={skipPageResetRef.current}
/>
)
diff --git a/examples/kitchen-sink/src/App.js b/examples/kitchen-sink/src/App.js
index 1ef6c61..cf6183e 100644
--- a/examples/kitchen-sink/src/App.js
+++ b/examples/kitchen-sink/src/App.js
@@ -232,8 +232,8 @@ function fuzzyTextFilterFn(rows, id, filterValue) {
// Let the table remove the filter if the string is empty
fuzzyTextFilterFn.autoRemove = val => !val
-// Be sure to pass our updateMyData and the disablePageResetOnDataChange option
-function Table({ columns, data, updateMyData, disablePageResetOnDataChange }) {
+// Be sure to pass our updateMyData and the skipReset option
+function Table({ columns, data, updateMyData, skipReset }) {
const filterTypes = React.useMemo(
() => ({
// Add a new fuzzyTextFilterFn filter type.
@@ -305,8 +305,9 @@ function Table({ columns, data, updateMyData, disablePageResetOnDataChange }) {
// cell renderer!
updateMyData,
// We also need to pass this so the page doesn't change
- // when we edit the data
- disablePageResetOnDataChange,
+ // when we edit the data. Undefined tells it to use the default
+ getResetPageDeps: skipReset ? false : undefined,
+ getResetSelectedRowPathsDeps: skipReset ? false : undefined,
},
useFilters,
useGroupBy,
@@ -350,37 +351,36 @@ function Table({ columns, data, updateMyData, disablePageResetOnDataChange }) {
))}
- {page.map(
- row => {
- prepareRow(row);
- return (
-
- {row.cells.map(cell => {
- return (
- |
- {cell.isGrouped ? (
- // If it's a grouped cell, add an expander and row count
- <>
-
- {row.isExpanded ? '👇' : '👉'}
- {' '}
- {cell.render('Cell', { editable: false })} (
- {row.subRows.length})
- >
- ) : cell.isAggregated ? (
- // If the cell is aggregated, use the Aggregated
- // renderer for cell
- cell.render('Aggregated')
- ) : cell.isRepeatedValue ? null : ( // For cells with repeated values, render null
- // Otherwise, just render the regular cell
- cell.render('Cell', { editable: true })
- )}
- |
- )
- })}
-
- )}
- )}
+ {page.map(row => {
+ prepareRow(row)
+ return (
+
+ {row.cells.map(cell => {
+ return (
+ |
+ {cell.isGrouped ? (
+ // If it's a grouped cell, add an expander and row count
+ <>
+
+ {row.isExpanded ? '👇' : '👉'}
+ {' '}
+ {cell.render('Cell', { editable: false })} (
+ {row.subRows.length})
+ >
+ ) : cell.isAggregated ? (
+ // If the cell is aggregated, use the Aggregated
+ // renderer for cell
+ cell.render('Aggregated')
+ ) : cell.isRepeatedValue ? null : ( // For cells with repeated values, render null
+ // Otherwise, just render the regular cell
+ cell.render('Cell', { editable: true })
+ )}
+ |
+ )
+ })}
+
+ )
+ })}
{/*
@@ -580,14 +580,14 @@ function App() {
// We need to keep the table from resetting the pageIndex when we
// Update data. So we can keep track of that flag with a ref.
- const skipPageResetRef = React.useRef(false)
+ const skipResetRef = React.useRef(false)
// When our cell renderer calls updateMyData, we'll use
// the rowIndex, columnID and new value to update the
// original data
const updateMyData = (rowIndex, columnID, value) => {
// We also turn on the flag to not reset the page
- skipPageResetRef.current = true
+ skipResetRef.current = true
setData(old =>
old.map((row, index) => {
if (index === rowIndex) {
@@ -605,14 +605,14 @@ function App() {
// so that if data actually changes when we're not
// editing it, the page is reset
React.useEffect(() => {
- skipPageResetRef.current = false
+ skipResetRef.current = false
}, [data])
// Let's add a data resetter/randomizer to help
// illustrate that flow...
const resetData = () => {
// Don't reset the page when we do this
- skipPageResetRef.current = true
+ skipResetRef.current = true
setData(originalData)
}
@@ -623,7 +623,7 @@ function App() {
columns={columns}
data={data}
updateMyData={updateMyData}
- disablePageResetOnDataChange={skipPageResetRef.current}
+ skipReset={skipResetRef.current}
/>
)
diff --git a/index.d.ts b/index.d.ts
index f26ca33..d157ea1 100644
--- a/index.d.ts
+++ b/index.d.ts
@@ -213,6 +213,7 @@ export type UseExpandedOptions
= Partial<{
getSubRows: (row: Row, relativeIndex: number) => Array>
manualExpandedKey: IdType
paginateExpandedRows: boolean
+ getResetExpandedDeps: (i: TableInstance) => Array
}>
export interface UseExpandedHooks {
@@ -250,6 +251,7 @@ export type UseFiltersOptions = Partial<{
manualFilters: boolean
disableFilters: boolean
filterTypes: Filters
+ getResetFiltersDeps: (i: TableInstance) => Array
}>
export interface UseFiltersState {
@@ -323,6 +325,7 @@ export type UseGroupByOptions = Partial<{
rows: Array>,
columnId: IdType
) => Record>
+ getResetGroupByDeps: (i: TableInstance) => Array
}>
export interface UseGroupByHooks {
@@ -403,7 +406,7 @@ export namespace usePagination {
export type UsePaginationOptions = Partial<{
pageCount: number
manualPagination: boolean
- disablePageResetOnDataChange: boolean
+ getResetPageDeps: (i: TableInstance) => Array
paginateExpandedRows: boolean
}>
@@ -435,6 +438,7 @@ export namespace useRowSelect {
export type UseRowSelectOptions = Partial<{
manualRowSelectedKey: IdType
+ getResetSelectedRowPathsDeps: (i: TableInstance) => Array
}>
export interface UseRowSelectHooks {
@@ -525,6 +529,7 @@ export type UseSortByOptions = Partial<{
directions: boolean[]
) => Array>
sortTypes: Record>
+ getResetSortByDeps: (i: TableInstance) => Array
}>
export interface UseSortByHooks {
diff --git a/src/plugin-hooks/useExpanded.js b/src/plugin-hooks/useExpanded.js
index f63e19f..967ad6b 100755
--- a/src/plugin-hooks/useExpanded.js
+++ b/src/plugin-hooks/useExpanded.js
@@ -1,6 +1,11 @@
import React from 'react'
-import { mergeProps, applyPropHooks, expandRows } from '../utils'
+import {
+ mergeProps,
+ applyPropHooks,
+ expandRows,
+ safeUseLayoutEffect,
+} from '../utils'
import { addActions, actions } from '../actions'
import { defaultState } from '../hooks/useTable'
@@ -15,6 +20,8 @@ export const useExpanded = hooks => {
useExpanded.pluginName = 'useExpanded'
+const defaultGetResetExpandedDeps = instance => [instance.data]
+
function useMain(instance) {
const {
debug,
@@ -25,8 +32,27 @@ function useMain(instance) {
hooks,
state: { expanded },
setState,
+ getResetExpandedDeps = defaultGetResetExpandedDeps,
} = instance
+ // Bypass any effects from firing when this changes
+ const isMountedRef = React.useRef()
+ safeUseLayoutEffect(() => {
+ if (isMountedRef.current) {
+ setState(
+ old => ({
+ ...old,
+ expanded: [],
+ }),
+ actions.pageChange
+ )
+ }
+ isMountedRef.current = true
+ }, [
+ setState,
+ ...(getResetExpandedDeps ? getResetExpandedDeps(instance) : []),
+ ])
+
const toggleExpandedByPath = (path, set) => {
const key = path.join('.')
diff --git a/src/plugin-hooks/useFilters.js b/src/plugin-hooks/useFilters.js
index c2187c2..8978260 100755
--- a/src/plugin-hooks/useFilters.js
+++ b/src/plugin-hooks/useFilters.js
@@ -1,6 +1,6 @@
import React from 'react'
-import { getFirstDefined, isFunction } from '../utils'
+import { getFirstDefined, isFunction, safeUseLayoutEffect } from '../utils'
import * as filterTypes from '../filterTypes'
import { addActions, actions } from '../actions'
import { defaultState } from '../hooks/useTable'
@@ -27,11 +27,27 @@ function useMain(instance) {
disableFilters,
state: { filters },
setState,
+ getResetFiltersDeps = false,
} = instance
const preFilteredRows = rows
const preFilteredFlatRows = flatRows
+ // Bypass any effects from firing when this changes
+ const isMountedRef = React.useRef()
+ safeUseLayoutEffect(() => {
+ if (isMountedRef.current) {
+ setState(
+ old => ({
+ ...old,
+ filters: {},
+ }),
+ actions.pageChange
+ )
+ }
+ isMountedRef.current = true
+ }, [setState, ...(getResetFiltersDeps ? getResetFiltersDeps(instance) : [])])
+
const setFilter = (id, updater) => {
const column = flatColumns.find(d => d.id === id)
diff --git a/src/plugin-hooks/usePagination.js b/src/plugin-hooks/usePagination.js
index 42d3258..08cdcd1 100755
--- a/src/plugin-hooks/usePagination.js
+++ b/src/plugin-hooks/usePagination.js
@@ -16,19 +16,24 @@ export const usePagination = hooks => {
usePagination.pluginName = 'usePagination'
+const defaultGetResetPageDeps = ({
+ rows,
+ manualPagination,
+ state: { filters, groupBy, sortBy },
+}) => [manualPagination ? null : rows, filters, groupBy, sortBy]
+
function useMain(instance) {
const {
- data,
rows,
manualPagination,
- disablePageResetOnDataChange,
+ getResetPageDeps = defaultGetResetPageDeps,
manualExpandedKey = 'expanded',
debug,
plugins,
pageCount: userPageCount,
paginateExpandedRows = true,
expandSubRows = true,
- state: { pageSize, pageIndex, filters, groupBy, sortBy, expanded },
+ state: { pageSize, pageIndex, expanded },
setState,
} = instance
@@ -39,19 +44,10 @@ function useMain(instance) {
[]
)
- const rowDep = manualPagination ? null : data
-
- const isPageIndexMountedRef = React.useRef()
-
// Bypass any effects from firing when this changes
- const disablePageResetOnDataChangeRef = React.useRef()
- disablePageResetOnDataChangeRef.current = disablePageResetOnDataChange
-
+ const isMountedRef = React.useRef()
safeUseLayoutEffect(() => {
- if (
- isPageIndexMountedRef.current &&
- !disablePageResetOnDataChangeRef.current
- ) {
+ if (isMountedRef.current) {
setState(
old => ({
...old,
@@ -60,8 +56,8 @@ function useMain(instance) {
actions.pageChange
)
}
- isPageIndexMountedRef.current = true
- }, [setState, rowDep, filters, groupBy, sortBy])
+ isMountedRef.current = true
+ }, [setState, ...(getResetPageDeps ? getResetPageDeps(instance) : [])])
const pageCount = manualPagination
? userPageCount
diff --git a/src/plugin-hooks/useRowSelect.js b/src/plugin-hooks/useRowSelect.js
index f02d1c8..d4b790e 100644
--- a/src/plugin-hooks/useRowSelect.js
+++ b/src/plugin-hooks/useRowSelect.js
@@ -49,14 +49,15 @@ function useRows(rows, instance) {
return rows
}
+const defaultGetResetSelectedRowPathsDeps = ({ rows }) => [rows]
+
function useMain(instance) {
const {
hooks,
manualRowSelectedKey = 'isSelected',
- disableSelectedRowsResetOnDataChange,
plugins,
flatRows,
- data,
+ getResetSelectedRowPathsDeps = defaultGetResetSelectedRowPathsDeps,
state: { selectedRowPaths },
setState,
} = instance
@@ -78,17 +79,10 @@ function useMain(instance) {
}
}
- const isRowSelectedMountedRef = React.useRef()
-
// Bypass any effects from firing when this changes
- const disableSelectedRowsResetOnDataChangeRef = React.useRef()
- disableSelectedRowsResetOnDataChangeRef.current = disableSelectedRowsResetOnDataChange
-
+ const isMountedRef = React.useRef()
safeUseLayoutEffect(() => {
- if (
- isRowSelectedMountedRef.current &&
- !disableSelectedRowsResetOnDataChangeRef.current
- ) {
+ if (isMountedRef.current) {
setState(
old => ({
...old,
@@ -97,8 +91,13 @@ function useMain(instance) {
actions.pageChange
)
}
- isRowSelectedMountedRef.current = true
- }, [setState, data])
+ isMountedRef.current = true
+ }, [
+ setState,
+ ...(getResetSelectedRowPathsDeps
+ ? getResetSelectedRowPathsDeps(instance)
+ : []),
+ ])
const toggleRowSelectedAll = set => {
setState(old => {
diff --git a/src/plugin-hooks/useSortBy.js b/src/plugin-hooks/useSortBy.js
index e361ea2..b46f139 100755
--- a/src/plugin-hooks/useSortBy.js
+++ b/src/plugin-hooks/useSortBy.js
@@ -1,6 +1,6 @@
import React from 'react'
-import { ensurePluginOrder, defaultColumn } from '../utils'
+import { ensurePluginOrder, defaultColumn, safeUseLayoutEffect } from '../utils'
import { addActions, actions } from '../actions'
import { defaultState } from '../hooks/useTable'
import * as sortTypes from '../sortTypes'
@@ -44,12 +44,28 @@ function useMain(instance) {
state: { sortBy },
setState,
plugins,
+ getResetSortByDeps = false,
} = instance
ensurePluginOrder(plugins, ['useFilters'], 'useSortBy', [])
// Add custom hooks
hooks.getSortByToggleProps = []
+ // Bypass any effects from firing when this changes
+ const isMountedRef = React.useRef()
+ safeUseLayoutEffect(() => {
+ if (isMountedRef.current) {
+ setState(
+ old => ({
+ ...old,
+ sortBy: [],
+ }),
+ actions.pageChange
+ )
+ }
+ isMountedRef.current = true
+ }, [setState, ...(getResetSortByDeps ? getResetSortByDeps(instance) : [])])
+
// Updates sorting based on a columnID, desc flag and multi flag
const toggleSortBy = (columnID, desc, multi) => {
return setState(old => {
@@ -93,7 +109,8 @@ function useMain(instance) {
!hasDescDefined && // Must not be setting desc
(multi ? !disableMultiRemove : true) && // If multi, don't allow if disableMultiRemove
((existingSortBy && // Finally, detect if it should indeed be removed
- (existingSortBy.desc && !sortDescFirst)) ||
+ existingSortBy.desc &&
+ !sortDescFirst) ||
(!existingSortBy.desc && sortDescFirst))
) {
action = 'remove'