Files
react-table/src/plugin-hooks/useExpanded.js
T
Tanner LinsleyandGitHub 8ba553871f Add useColumnVisibility as core hook (#1700)
* Update utils.js

* Update useTable.js

* Create useColumnVisibility.js

* Update useColumnVisibility.js

* Update useColumnVisibility.js

* Convert to core hook, use new reducerHanndler/actions

* Add useColumnVisibility internal hook
2019-12-05 15:45:25 -05:00

161 lines
3.4 KiB
JavaScript
Executable File

import React from 'react'
import {
actions,
reducerHandlers,
mergeProps,
applyPropHooks,
expandRows,
safeUseLayoutEffect,
} from '../utils'
const pluginName = 'useExpanded'
// Actions
actions.toggleExpandedByPath = 'toggleExpandedByPath'
actions.resetExpanded = 'resetExpanded'
// Reducer
reducerHandlers[pluginName] = (state, action) => {
if (action.type === actions.init) {
return {
expanded: [],
...state,
}
}
if (action.type === actions.resetExpanded) {
return {
...state,
expanded: [],
}
}
if (action.type === actions.toggleExpandedByPath) {
const { path, expanded } = action
const key = path.join('.')
const exists = state.expanded.includes(key)
const shouldExist = typeof set !== 'undefined' ? expanded : !exists
let newExpanded = new Set(state.expanded)
if (!exists && shouldExist) {
newExpanded.add(key)
} else if (exists && !shouldExist) {
newExpanded.delete(key)
} else {
return state
}
return {
...state,
expanded: [...newExpanded.values()],
}
}
}
export const useExpanded = hooks => {
hooks.getExpandedToggleProps = []
hooks.useInstance.push(useInstance)
}
useExpanded.pluginName = pluginName
const defaultGetResetExpandedDeps = ({ data }) => [data]
function useInstance(instance) {
const {
debug,
rows,
manualExpandedKey = 'expanded',
paginateExpandedRows = true,
expandSubRows = true,
hooks,
state: { expanded },
dispatch,
getResetExpandedDeps = defaultGetResetExpandedDeps,
} = instance
// Bypass any effects from firing when this changes
const isMountedRef = React.useRef()
safeUseLayoutEffect(() => {
if (isMountedRef.current) {
dispatch({ type: actions.resetExpanded })
}
isMountedRef.current = true
}, [
dispatch,
...(getResetExpandedDeps ? getResetExpandedDeps(instance) : []),
])
const toggleExpandedByPath = (path, expanded) => {
dispatch({ type: actions.toggleExpandedByPath, path, expanded })
}
// use reference to avoid memory leak in #1608
const instanceRef = React.useRef()
instanceRef.current = instance
hooks.prepareRow.push(row => {
row.toggleExpanded = set => toggleExpandedByPath(row.path, set)
row.getExpandedToggleProps = props => {
return mergeProps(
{
onClick: e => {
e.persist()
row.toggleExpanded()
},
style: {
cursor: 'pointer',
},
title: 'Toggle Expanded',
},
applyPropHooks(
instanceRef.current.hooks.getExpandedToggleProps,
row,
instanceRef.current
),
props
)
}
return row
})
const expandedRows = React.useMemo(() => {
if (process.env.NODE_ENV !== 'production' && debug)
console.info('getExpandedRows')
if (paginateExpandedRows) {
return expandRows(rows, { manualExpandedKey, expanded, expandSubRows })
}
return rows
}, [
debug,
paginateExpandedRows,
rows,
manualExpandedKey,
expanded,
expandSubRows,
])
const expandedDepth = findExpandedDepth(expanded)
return {
...instance,
toggleExpandedByPath,
expandedDepth,
rows: expandedRows,
}
}
function findExpandedDepth(expanded) {
let maxDepth = 0
expanded.forEach(key => {
const path = key.split('.')
maxDepth = Math.max(maxDepth, path.length)
})
return maxDepth
}