Files
react-table/src/plugin-hooks/useResizeColumns.js
T
Jason LawandTanner Linsley 0a512adaf0 fix: memory leak fix (#1610)
* fix: memory leak

* Style change
2019-11-29 21:14:04 -07:00

146 lines
3.4 KiB
JavaScript

import React from 'react'
import { defaultState } from '../hooks/useTable'
import { defaultColumn, getFirstDefined } from '../utils'
import { mergeProps, applyPropHooks } from '../utils'
defaultState.columnResizing = {
columnWidths: {},
}
defaultColumn.canResize = true
export const useResizeColumns = hooks => {
hooks.useBeforeDimensions.push(useBeforeDimensions)
}
useResizeColumns.pluginName = 'useResizeColumns'
const useBeforeDimensions = instance => {
instance.hooks.getResizerProps = []
const {
flatHeaders,
disableResizing,
hooks: { getHeaderProps },
state: { columnResizing },
setState,
} = instance
getHeaderProps.push(() => {
return {
style: {
position: 'relative',
},
}
})
const onMouseDown = (e, header) => {
const headersToResize = getLeafHeaders(header)
const startWidths = headersToResize.map(header => header.totalWidth)
const startX = e.clientX
const onMouseMove = e => {
const currentX = e.clientX
const deltaX = currentX - startX
const percentageDeltaX = deltaX / headersToResize.length
const newColumnWidths = {}
headersToResize.forEach((header, index) => {
newColumnWidths[header.id] = Math.max(
startWidths[index] + percentageDeltaX,
0
)
})
setState(old => ({
...old,
columnResizing: {
...old.columnResizing,
columnWidths: {
...old.columnResizing.columnWidths,
...newColumnWidths,
},
},
}))
}
const onMouseUp = e => {
document.removeEventListener('mousemove', onMouseMove)
document.removeEventListener('mouseup', onMouseUp)
setState(old => ({
...old,
columnResizing: {
...old.columnResizing,
startX: null,
isResizingColumn: null,
},
}))
}
document.addEventListener('mousemove', onMouseMove)
document.addEventListener('mouseup', onMouseUp)
setState(old => ({
...old,
columnResizing: {
...old.columnResizing,
startX,
isResizingColumn: header.id,
},
}))
}
// use reference to avoid memory leak in #1608
const instanceRef = React.useRef()
instanceRef.current = instance
flatHeaders.forEach(header => {
const canResize = getFirstDefined(
header.disableResizing === true ? false : undefined,
disableResizing === true ? false : undefined,
true
)
header.canResize = canResize
header.width = columnResizing.columnWidths[header.id] || header.width
header.isResizing = columnResizing.isResizingColumn === header.id
if (canResize) {
header.getResizerProps = userProps => {
return mergeProps(
{
onMouseDown: e => e.persist() || onMouseDown(e, header),
style: {
cursor: 'ew-resize',
},
draggable: false,
},
applyPropHooks(
instanceRef.current.hooks.getResizerProps,
header,
instanceRef.current
),
userProps
)
}
}
})
return instance
}
function getLeafHeaders(header) {
const leafHeaders = []
const recurseHeader = header => {
if (header.columns && header.columns.length) {
header.columns.map(recurseHeader)
}
leafHeaders.push(header)
}
recurseHeader(header)
return leafHeaders
}