Use effect dependency user call

This commit is contained in:
Tanner Linsley
2019-11-20 12:09:24 -07:00
parent e2728d0fdb
commit 3187061041
12 changed files with 237 additions and 137 deletions
+6 -6
View File
@@ -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,
+9
View File
@@ -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
+39 -4
View File
@@ -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
+15 -17
View File
@@ -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 }) {
))}
</thead>
<tbody {...getTableBodyProps()}>
{page.map(
(row, i) => {
prepareRow(row);
return (
<tr {...row.getRowProps()}>
{row.cells.map(cell => {
return (
<td {...cell.getCellProps()}>{cell.render('Cell')}</td>
)
})}
</tr>
)}
)}
{page.map((row, i) => {
prepareRow(row)
return (
<tr {...row.getRowProps()}>
{row.cells.map(cell => {
return <td {...cell.getCellProps()}>{cell.render('Cell')}</td>
})}
</tr>
)
})}
</tbody>
</table>
<div className="pagination">
@@ -274,7 +272,7 @@ function App() {
columns={columns}
data={data}
updateMyData={updateMyData}
disablePageResetOnDataChange={skipPageReset}
skipPageReset={skipPageReset}
/>
</Styles>
)
+35 -36
View File
@@ -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 }) {
))}
</thead>
<tbody {...getTableBodyProps()}>
{page.map(
row => {
prepareRow(row);
return (
<tr {...row.getRowProps()}>
{row.cells.map(cell => {
return (
<td {...cell.getCellProps()}>
{cell.isGrouped ? (
// If it's a grouped cell, add an expander and row count
<>
<span {...row.getExpandedToggleProps()}>
{row.isExpanded ? '👇' : '👉'}
</span>{' '}
{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 })
)}
</td>
)
})}
</tr>
)}
)}
{page.map(row => {
prepareRow(row)
return (
<tr {...row.getRowProps()}>
{row.cells.map(cell => {
return (
<td {...cell.getCellProps()}>
{cell.isGrouped ? (
// If it's a grouped cell, add an expander and row count
<>
<span {...row.getExpandedToggleProps()}>
{row.isExpanded ? '👇' : '👉'}
</span>{' '}
{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 })
)}
</td>
)
})}
</tr>
)
})}
</tbody>
</table>
{/*
@@ -623,7 +622,7 @@ function App() {
columns={columns}
data={data}
updateMyData={updateMyData}
disablePageResetOnDataChange={skipPageResetRef.current}
skipPageReset={skipPageResetRef.current}
/>
</Styles>
)
+40 -40
View File
@@ -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 }) {
))}
</thead>
<tbody {...getTableBodyProps()}>
{page.map(
row => {
prepareRow(row);
return (
<tr {...row.getRowProps()}>
{row.cells.map(cell => {
return (
<td {...cell.getCellProps()}>
{cell.isGrouped ? (
// If it's a grouped cell, add an expander and row count
<>
<span {...row.getExpandedToggleProps()}>
{row.isExpanded ? '👇' : '👉'}
</span>{' '}
{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 })
)}
</td>
)
})}
</tr>
)}
)}
{page.map(row => {
prepareRow(row)
return (
<tr {...row.getRowProps()}>
{row.cells.map(cell => {
return (
<td {...cell.getCellProps()}>
{cell.isGrouped ? (
// If it's a grouped cell, add an expander and row count
<>
<span {...row.getExpandedToggleProps()}>
{row.isExpanded ? '👇' : '👉'}
</span>{' '}
{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 })
)}
</td>
)
})}
</tr>
)
})}
</tbody>
</table>
{/*
@@ -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}
/>
</Styles>
)
Vendored
+6 -1
View File
@@ -213,6 +213,7 @@ export type UseExpandedOptions<D extends object> = Partial<{
getSubRows: (row: Row<D>, relativeIndex: number) => Array<Row<D>>
manualExpandedKey: IdType<D>
paginateExpandedRows: boolean
getResetExpandedDeps: (i: TableInstance) => Array<any>
}>
export interface UseExpandedHooks<D extends object> {
@@ -250,6 +251,7 @@ export type UseFiltersOptions<D extends object> = Partial<{
manualFilters: boolean
disableFilters: boolean
filterTypes: Filters<D>
getResetFiltersDeps: (i: TableInstance) => Array<any>
}>
export interface UseFiltersState<D extends object> {
@@ -323,6 +325,7 @@ export type UseGroupByOptions<D extends object> = Partial<{
rows: Array<Row<D>>,
columnId: IdType<D>
) => Record<string, Row<D>>
getResetGroupByDeps: (i: TableInstance) => Array<any>
}>
export interface UseGroupByHooks<D extends object> {
@@ -403,7 +406,7 @@ export namespace usePagination {
export type UsePaginationOptions<D extends object> = Partial<{
pageCount: number
manualPagination: boolean
disablePageResetOnDataChange: boolean
getResetPageDeps: (i: TableInstance) => Array<any>
paginateExpandedRows: boolean
}>
@@ -435,6 +438,7 @@ export namespace useRowSelect {
export type UseRowSelectOptions<D extends object> = Partial<{
manualRowSelectedKey: IdType<D>
getResetSelectedRowPathsDeps: (i: TableInstance) => Array<any>
}>
export interface UseRowSelectHooks<D extends object> {
@@ -525,6 +529,7 @@ export type UseSortByOptions<D extends object> = Partial<{
directions: boolean[]
) => Array<Row<D>>
sortTypes: Record<string, SortByFn<D>>
getResetSortByDeps: (i: TableInstance) => Array<any>
}>
export interface UseSortByHooks<D extends object> {
+27 -1
View File
@@ -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('.')
+17 -1
View File
@@ -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)
+12 -16
View File
@@ -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
+12 -13
View File
@@ -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 => {
+19 -2
View File
@@ -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'