UNPKG

react-table

Version:

Hooks for building lightweight, fast and extendable datagrids for React

166 lines (138 loc) 3.83 kB
import React from 'react' import { actions, functionalUpdate, useMountedLayoutEffect, useGetLatest, } from '../publicUtils' const defaultInitialRowStateAccessor = row => ({}) const defaultInitialCellStateAccessor = cell => ({}) // Actions actions.setRowState = 'setRowState' actions.setCellState = 'setCellState' actions.resetRowState = 'resetRowState' export const useRowState = hooks => { hooks.stateReducers.push(reducer) hooks.useInstance.push(useInstance) hooks.prepareRow.push(prepareRow) } useRowState.pluginName = 'useRowState' function reducer(state, action, previousState, instance) { const { initialRowStateAccessor = defaultInitialRowStateAccessor, initialCellStateAccessor = defaultInitialCellStateAccessor, rowsById, } = instance if (action.type === actions.init) { return { rowState: {}, ...state, } } if (action.type === actions.resetRowState) { return { ...state, rowState: instance.initialState.rowState || {}, } } if (action.type === actions.setRowState) { const { rowId, value } = action const oldRowState = typeof state.rowState[rowId] !== 'undefined' ? state.rowState[rowId] : initialRowStateAccessor(rowsById[rowId]) return { ...state, rowState: { ...state.rowState, [rowId]: functionalUpdate(value, oldRowState), }, } } if (action.type === actions.setCellState) { const { rowId, columnId, value } = action const oldRowState = typeof state.rowState[rowId] !== 'undefined' ? state.rowState[rowId] : initialRowStateAccessor(rowsById[rowId]) const oldCellState = typeof oldRowState?.cellState?.[columnId] !== 'undefined' ? oldRowState.cellState[columnId] : initialCellStateAccessor( rowsById[rowId]?.cells?.find(cell => cell.column.id === columnId) ) return { ...state, rowState: { ...state.rowState, [rowId]: { ...oldRowState, cellState: { ...(oldRowState.cellState || {}), [columnId]: functionalUpdate(value, oldCellState), }, }, }, } } } function useInstance(instance) { const { autoResetRowState = true, data, dispatch } = instance const setRowState = React.useCallback( (rowId, value) => dispatch({ type: actions.setRowState, rowId, value, }), [dispatch] ) const setCellState = React.useCallback( (rowId, columnId, value) => dispatch({ type: actions.setCellState, rowId, columnId, value, }), [dispatch] ) const getAutoResetRowState = useGetLatest(autoResetRowState) useMountedLayoutEffect(() => { if (getAutoResetRowState()) { dispatch({ type: actions.resetRowState }) } }, [data]) Object.assign(instance, { setRowState, setCellState, }) } function prepareRow(row, { instance }) { const { initialRowStateAccessor = defaultInitialRowStateAccessor, initialCellStateAccessor = defaultInitialCellStateAccessor, state: { rowState }, } = instance if (row) { row.state = typeof rowState[row.id] !== 'undefined' ? rowState[row.id] : initialRowStateAccessor(row) row.setState = updater => { return instance.setRowState(row.id, updater) } row.cells.forEach(cell => { if (!row.state.cellState) { row.state.cellState = {} } cell.state = typeof row.state.cellState[cell.column.id] !== 'undefined' ? row.state.cellState[cell.column.id] : initialCellStateAccessor(cell) cell.setState = updater => { return instance.setCellState(row.id, cell.column.id, updater) } }) } }