style: lock prettier version, fix sorting example

This commit is contained in:
tannerlinsley 2019-08-16 07:20:52 -06:00
parent 4712cf8af5
commit 40884e9a44
9 changed files with 283 additions and 303 deletions

View File

@ -0,0 +1,3 @@
{
"infiniteLoopProtection": false
}

View File

@ -36,7 +36,9 @@ const Styles = styled.div`
`
// Define a default UI for filtering
function DefaultColumnFilter({ filterValue, preFilteredRows, setFilter }) {
function DefaultColumnFilter({
column: { filterValue, preFilteredRows, setFilter },
}) {
const count = preFilteredRows.length
return (
@ -52,19 +54,18 @@ function DefaultColumnFilter({ filterValue, preFilteredRows, setFilter }) {
// This is a custom filter UI for selecting
// a unique option from a list
function SelectColumnFilter({ filterValue, setFilter, preFilteredRows, id }) {
function SelectColumnFilter({
column: { filterValue, setFilter, preFilteredRows, id },
}) {
// Calculate the options for filtering
// using the preFilteredRows
const options = React.useMemo(
() => {
const options = new Set()
preFilteredRows.forEach(row => {
options.add(row.values[id])
})
return [...options.values()]
},
[id, preFilteredRows]
)
const options = React.useMemo(() => {
const options = new Set()
preFilteredRows.forEach(row => {
options.add(row.values[id])
})
return [...options.values()]
}, [id, preFilteredRows])
// Render a multi-select box
return (
@ -87,22 +88,21 @@ function SelectColumnFilter({ filterValue, setFilter, preFilteredRows, id }) {
// This is a custom filter UI that uses a
// slider to set the filter value between a column's
// min and max values
function SliderColumnFilter({ filterValue, setFilter, preFilteredRows, id }) {
function SliderColumnFilter({
column: { filterValue, setFilter, preFilteredRows, id },
}) {
// Calculate the min and max
// using the preFilteredRows
const [min, max] = React.useMemo(
() => {
let min = 0
let max = 0
preFilteredRows.forEach(row => {
min = Math.min(row.values[id], min)
max = Math.max(row.values[id], max)
})
return [min, max]
},
[id, preFilteredRows]
)
const [min, max] = React.useMemo(() => {
let min = preFilteredRows.length ? preFilteredRows[0].values[id] : 0
let max = preFilteredRows.length ? preFilteredRows[0].values[id] : 0
preFilteredRows.forEach(row => {
min = Math.min(row.values[id], min)
max = Math.max(row.values[id], max)
})
return [min, max]
}, [id, preFilteredRows])
return (
<>
@ -124,23 +124,17 @@ function SliderColumnFilter({ filterValue, setFilter, preFilteredRows, id }) {
// filter. It uses two number boxes and filters rows to
// ones that have values between the two
function NumberRangeColumnFilter({
filterValue = [],
preFilteredRows,
setFilter,
id,
column: { filterValue = [], preFilteredRows, setFilter, id },
}) {
const [min, max] = React.useMemo(
() => {
let min = 0
let max = 0
preFilteredRows.forEach(row => {
min = Math.min(row.values[id], min)
max = Math.max(row.values[id], max)
})
return [min, max]
},
[id, preFilteredRows]
)
const [min, max] = React.useMemo(() => {
let min = preFilteredRows.length ? preFilteredRows[0].values[id] : 0
let max = preFilteredRows.length ? preFilteredRows[0].values[id] : 0
preFilteredRows.forEach(row => {
min = Math.min(row.values[id], min)
max = Math.max(row.values[id], max)
})
return [min, max]
}, [id, preFilteredRows])
return (
<div
@ -226,9 +220,9 @@ function Table({ columns, data }) {
useFilters // useFilters!
)
// We don't want to render all 2000 rows for this example, so cap
// it at 20 for this use case
const firstPageRows = rows.slice(0, 20)
// We don't want to render all of the rows for this example, so cap
// it for this use case
const firstPageRows = rows.slice(0, 10)
return (
<>
@ -337,7 +331,7 @@ function App() {
[]
)
const data = React.useMemo(() => makeData(10000), [])
const data = React.useMemo(() => makeData(100000), [])
return (
<Styles>

View File

@ -80,6 +80,7 @@
"jest-watch-select-projects": "^0.1.2",
"jest-watch-typeahead": "^0.3.1",
"lint-staged": "^9.2.1",
"prettier": "^1.18.2",
"prop-types": "^15.5.0",
"react": "^16.9.0",
"react-dom": "^16.9.0",

View File

@ -102,30 +102,27 @@ export const useTable = (props, ...plugins) => {
])
// Allow hooks to decorate columns (and trigger this memoization via deps)
columns = React.useMemo(
() => {
if (process.env.NODE_ENV === 'development' && debug)
console.time('hooks.columnsBeforeHeaderGroups')
const newColumns = applyHooks(
instanceRef.current.hooks.columnsBeforeHeaderGroups,
columns,
instanceRef.current
)
if (process.env.NODE_ENV === 'development' && debug)
console.timeEnd('hooks.columnsBeforeHeaderGroups')
return newColumns
},
[
columns = React.useMemo(() => {
if (process.env.NODE_ENV === 'development' && debug)
console.time('hooks.columnsBeforeHeaderGroups')
const newColumns = applyHooks(
instanceRef.current.hooks.columnsBeforeHeaderGroups,
columns,
debug,
// eslint-disable-next-line react-hooks/exhaustive-deps
...applyHooks(
instanceRef.current.hooks.columnsBeforeHeaderGroupsDeps,
[],
instanceRef.current
),
]
)
instanceRef.current
)
if (process.env.NODE_ENV === 'development' && debug)
console.timeEnd('hooks.columnsBeforeHeaderGroups')
return newColumns
}, [
columns,
debug,
// eslint-disable-next-line react-hooks/exhaustive-deps
...applyHooks(
instanceRef.current.hooks.columnsBeforeHeaderGroupsDeps,
[],
instanceRef.current
),
])
// Make the headerGroups
const headerGroups = React.useMemo(
@ -144,72 +141,69 @@ export const useTable = (props, ...plugins) => {
})
// Access the row model
const [rows, rowPaths, flatRows] = React.useMemo(
() => {
if (process.env.NODE_ENV === 'development' && debug)
console.time('getAccessedRows')
const [rows, rowPaths, flatRows] = React.useMemo(() => {
if (process.env.NODE_ENV === 'development' && debug)
console.time('getAccessedRows')
let flatRows = 0
const rowPaths = []
let flatRows = 0
const rowPaths = []
// Access the row's data
const accessRow = (originalRow, i, depth = 0, parentPath = []) => {
// Keep the original reference around
const original = originalRow
// Access the row's data
const accessRow = (originalRow, i, depth = 0, parentPath = []) => {
// Keep the original reference around
const original = originalRow
// Make the new path for the row
const path = [...parentPath, i]
// Make the new path for the row
const path = [...parentPath, i]
flatRows++
rowPaths.push(path.join('.'))
flatRows++
rowPaths.push(path.join('.'))
// Process any subRows
const subRows = originalRow[subRowsKey]
? originalRow[subRowsKey].map((d, i) =>
accessRow(d, i, depth + 1, path)
)
: []
const row = {
original,
index: i,
path, // used to create a key for each row even if not nested
subRows,
depth,
cells: [{}], // This is a dummy cell
}
// Override common array functions (and the dummy cell's getCellProps function)
// to show an error if it is accessed without calling prepareRow
const unpreparedAccessWarning = () => {
throw new Error(
'React-Table: You have not called prepareRow(row) one or more rows you are attempting to render.'
// Process any subRows
const subRows = originalRow[subRowsKey]
? originalRow[subRowsKey].map((d, i) =>
accessRow(d, i, depth + 1, path)
)
}
row.cells.map = unpreparedAccessWarning
row.cells.filter = unpreparedAccessWarning
row.cells.forEach = unpreparedAccessWarning
row.cells[0].getCellProps = unpreparedAccessWarning
: []
// Create the cells and values
row.values = {}
instanceRef.current.columns.forEach(column => {
row.values[column.id] = column.accessor
? column.accessor(originalRow, i, { subRows, depth, data })
: undefined
})
return row
const row = {
original,
index: i,
path, // used to create a key for each row even if not nested
subRows,
depth,
cells: [{}], // This is a dummy cell
}
// Use the resolved data
const accessedData = data.map((d, i) => accessRow(d, i))
if (process.env.NODE_ENV === 'development' && debug)
console.timeEnd('getAccessedRows')
return [accessedData, rowPaths, flatRows]
},
[debug, data, subRowsKey]
)
// Override common array functions (and the dummy cell's getCellProps function)
// to show an error if it is accessed without calling prepareRow
const unpreparedAccessWarning = () => {
throw new Error(
'React-Table: You have not called prepareRow(row) one or more rows you are attempting to render.'
)
}
row.cells.map = unpreparedAccessWarning
row.cells.filter = unpreparedAccessWarning
row.cells.forEach = unpreparedAccessWarning
row.cells[0].getCellProps = unpreparedAccessWarning
// Create the cells and values
row.values = {}
instanceRef.current.columns.forEach(column => {
row.values[column.id] = column.accessor
? column.accessor(originalRow, i, { subRows, depth, data })
: undefined
})
return row
}
// Use the resolved data
const accessedData = data.map((d, i) => accessRow(d, i))
if (process.env.NODE_ENV === 'development' && debug)
console.timeEnd('getAccessedRows')
return [accessedData, rowPaths, flatRows]
}, [debug, data, subRowsKey])
instanceRef.current.rows = rows
instanceRef.current.rowPaths = rowPaths

View File

@ -129,92 +129,87 @@ function useMain(instance) {
// cache for each row group (top-level rows, and each row's recursive subrows)
// This would make multi-filtering a lot faster though. Too far?
const filteredRows = React.useMemo(
() => {
if (manualFilters || !Object.keys(filters).length) {
return rows
}
const filteredRows = React.useMemo(() => {
if (manualFilters || !Object.keys(filters).length) {
return rows
}
if (process.env.NODE_ENV === 'development' && debug)
console.info('getFilteredRows')
if (process.env.NODE_ENV === 'development' && debug)
console.info('getFilteredRows')
// Filters top level and nested rows
const filterRows = (rows, depth = 0) => {
let filteredRows = rows
// Filters top level and nested rows
const filterRows = (rows, depth = 0) => {
let filteredRows = rows
filteredRows = Object.entries(filters).reduce(
(filteredSoFar, [columnID, filterValue]) => {
// Find the filters column
const column = columns.find(d => d.id === columnID)
filteredRows = Object.entries(filters).reduce(
(filteredSoFar, [columnID, filterValue]) => {
// Find the filters column
const column = columns.find(d => d.id === columnID)
if (depth === 0) {
column.preFilteredRows = filteredSoFar
}
if (depth === 0) {
column.preFilteredRows = filteredSoFar
}
if (!column) {
return filteredSoFar
}
if (!column) {
return filteredSoFar
}
const filterMethod = getFilterMethod(
column.filter,
userFilterTypes || {},
filterTypes
const filterMethod = getFilterMethod(
column.filter,
userFilterTypes || {},
filterTypes
)
if (!filterMethod) {
console.warn(
`Could not find a valid 'column.filter' for column with the ID: ${column.id}.`
)
if (!filterMethod) {
console.warn(
`Could not find a valid 'column.filter' for column with the ID: ${
column.id
}.`
)
return filteredSoFar
}
// Pass the rows, id, filterValue and column to the filterMethod
// to get the filtered rows back
return filterMethod(filteredSoFar, columnID, filterValue, column)
},
rows
)
// Apply the filter to any subRows
// We technically could do this recursively in the above loop,
// but that would severely hinder the API for the user, since they
// would be required to do that recursion in some scenarios
filteredRows = filteredRows.map(row => {
if (!row.subRows) {
return row
return filteredSoFar
}
return {
...row,
subRows:
row.subRows && row.subRows.length > 0
? filterRows(row.subRows, depth + 1)
: row.subRows,
}
})
return filteredRows
}
const filteredRows = filterRows(rows)
// Now that each filtered column has it's partially filtered rows,
// lets assign the final filtered rows to all of the other columns
const nonFilteredColumns = columns.filter(
column => !Object.keys(filters).includes(column.id)
// Pass the rows, id, filterValue and column to the filterMethod
// to get the filtered rows back
return filterMethod(filteredSoFar, columnID, filterValue, column)
},
rows
)
// This essentially enables faceted filter options to be built easily
// using every column's preFilteredRows value
nonFilteredColumns.forEach(column => {
column.preFilteredRows = filteredRows
// Apply the filter to any subRows
// We technically could do this recursively in the above loop,
// but that would severely hinder the API for the user, since they
// would be required to do that recursion in some scenarios
filteredRows = filteredRows.map(row => {
if (!row.subRows) {
return row
}
return {
...row,
subRows:
row.subRows && row.subRows.length > 0
? filterRows(row.subRows, depth + 1)
: row.subRows,
}
})
return filteredRows
},
[manualFilters, filters, debug, rows, columns, userFilterTypes]
)
}
return filterRows(rows)
}, [manualFilters, filters, debug, rows, columns, userFilterTypes])
React.useMemo(() => {
// Now that each filtered column has it's partially filtered rows,
// lets assign the final filtered rows to all of the other columns
const nonFilteredColumns = columns.filter(
column => !Object.keys(filters).includes(column.id)
)
// This essentially enables faceted filter options to be built easily
// using every column's preFilteredRows value
nonFilteredColumns.forEach(column => {
column.preFilteredRows = filteredRows
})
}, [columns, filteredRows, filters])
return {
...instance,

View File

@ -52,46 +52,40 @@ function useMain(instance) {
const isPageIndexMountedRef = React.useRef()
useLayoutEffect(
() => {
if (isPageIndexMountedRef.current) {
setState(
old => ({
...old,
pageIndex: 0,
}),
actions.pageChange
)
}
isPageIndexMountedRef.current = true
},
[setState, rowDep, filters, groupBy, sortBy]
)
useLayoutEffect(() => {
if (isPageIndexMountedRef.current) {
setState(
old => ({
...old,
pageIndex: 0,
}),
actions.pageChange
)
}
isPageIndexMountedRef.current = true
}, [setState, rowDep, filters, groupBy, sortBy])
const pages = React.useMemo(
() => {
if (manualPagination) {
return undefined
}
if (process.env.NODE_ENV === 'development' && debug)
console.info('getPages')
const pages = React.useMemo(() => {
if (manualPagination) {
return undefined
}
if (process.env.NODE_ENV === 'development' && debug)
console.info('getPages')
// Create a new pages with the first page ready to go.
const pages = rows.length ? [] : [[]]
// Create a new pages with the first page ready to go.
const pages = rows.length ? [] : [[]]
// Start the pageIndex and currentPage cursors
let cursor = 0
// Start the pageIndex and currentPage cursors
let cursor = 0
while (cursor < rows.length) {
const end = cursor + pageSize
pages.push(rows.slice(cursor, end))
cursor = end
}
while (cursor < rows.length) {
const end = cursor + pageSize
pages.push(rows.slice(cursor, end))
cursor = end
}
return pages
},
[debug, manualPagination, pageSize, rows]
)
return pages
}, [debug, manualPagination, pageSize, rows])
const pageCount = manualPagination ? userPageCount : pages.length

View File

@ -72,21 +72,18 @@ function useMain(instance) {
const rowsMountedRef = React.useRef()
// When data changes, reset row and cell state
React.useEffect(
() => {
if (rowsMountedRef.current) {
setState(old => {
return {
...old,
rowState: {},
}
}, actions.setRowState)
}
React.useEffect(() => {
if (rowsMountedRef.current) {
setState(old => {
return {
...old,
rowState: {},
}
}, actions.setRowState)
}
rowsMountedRef.current = true
},
[rows, setState]
)
rowsMountedRef.current = true
}, [rows, setState])
hooks.prepareRow.push(row => {
const pathKey = row.path.join('.')

View File

@ -202,72 +202,69 @@ function useMain(instance) {
column.sortedDesc = column.sorted ? column.sorted.desc : undefined
})
const sortedRows = React.useMemo(
() => {
if (manualSorting || !sortBy.length) {
return rows
}
if (process.env.NODE_ENV === 'development' && debug)
console.time('getSortedRows')
const sortedRows = React.useMemo(() => {
if (manualSorting || !sortBy.length) {
return rows
}
if (process.env.NODE_ENV === 'development' && debug)
console.time('getSortedRows')
const sortData = rows => {
// Use the orderByFn to compose multiple sortBy's together.
// This will also perform a stable sorting using the row index
// if needed.
const sortedData = orderByFn(
rows,
sortBy.map(sort => {
// Support custom sorting methods for each column
const { sortType } = columns.find(d => d.id === sort.id)
const sortData = rows => {
// Use the orderByFn to compose multiple sortBy's together.
// This will also perform a stable sorting using the row index
// if needed.
const sortedData = orderByFn(
rows,
sortBy.map(sort => {
// Support custom sorting methods for each column
const { sortType } = columns.find(d => d.id === sort.id)
// Look up sortBy functions in this order:
// column function
// column string lookup on user sortType
// column string lookup on built-in sortType
// default function
// default string lookup on user sortType
// default string lookup on built-in sortType
const sortMethod =
isFunction(sortType) ||
(userSortTypes || {})[sortType] ||
sortTypes[sortType] ||
sortTypes.alphanumeric
// Look up sortBy functions in this order:
// column function
// column string lookup on user sortType
// column string lookup on built-in sortType
// default function
// default string lookup on user sortType
// default string lookup on built-in sortType
const sortMethod =
isFunction(sortType) ||
(userSortTypes || {})[sortType] ||
sortTypes[sortType] ||
sortTypes.alphanumeric
// Return the correct sortFn
return (a, b) =>
sortMethod(a.values[sort.id], b.values[sort.id], sort.desc)
}),
// Map the directions
sortBy.map(sort => {
// Detect and use the sortInverted option
const { sortInverted } = columns.find(d => d.id === sort.id)
// Return the correct sortFn
return (a, b) =>
sortMethod(a.values[sort.id], b.values[sort.id], sort.desc)
}),
// Map the directions
sortBy.map(sort => {
// Detect and use the sortInverted option
const { sortInverted } = columns.find(d => d.id === sort.id)
if (sortInverted) {
return sort.desc
}
return !sort.desc
})
)
// If there are sub-rows, sort them
sortedData.forEach(row => {
if (!row.subRows || row.subRows.length <= 1) {
return
if (sortInverted) {
return sort.desc
}
row.subRows = sortData(row.subRows)
return !sort.desc
})
)
return sortedData
}
// If there are sub-rows, sort them
sortedData.forEach(row => {
if (!row.subRows || row.subRows.length <= 1) {
return
}
row.subRows = sortData(row.subRows)
})
if (process.env.NODE_ENV === 'development' && debug)
console.timeEnd('getSortedRows')
return sortedData
}
return sortData(rows)
},
[manualSorting, sortBy, debug, columns, rows, orderByFn, userSortTypes]
)
if (process.env.NODE_ENV === 'development' && debug)
console.timeEnd('getSortedRows')
return sortData(rows)
}, [manualSorting, sortBy, debug, columns, rows, orderByFn, userSortTypes])
return {
...instance,

View File

@ -6320,6 +6320,11 @@ prettier-linter-helpers@^1.0.0:
dependencies:
fast-diff "^1.1.2"
prettier@^1.18.2:
version "1.18.2"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.18.2.tgz#6823e7c5900017b4bd3acf46fe9ac4b4d7bda9ea"
integrity sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw==
pretty-format@^23.6.0:
version "23.6.0"
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-23.6.0.tgz#5eaac8eeb6b33b987b7fe6097ea6a8a146ab5760"