What an intriguing question!
When looking at the example's usage of
onPaginationChange: setPagination
, one might assume that the
onPaginationChange
function is invoked with the new state, but this is not the case.
The onPaginationChange
function actually receives an "updater" function, which takes the previous state and returns the new state. This mechanism aligns with React's setState
functionality, as it supports functional updates where the new state is defined based on the previous state.
In essence, instead of interpreting this:
onPaginationChange: (state) => setPagination(state),
It operates like this:
onPaginationChange: (updater) => setPagination(prevState => updater(prevState)),
The relevant snippet from the react-table source code is provided below:
setPagination: updater => {
const safeUpdater: Updater<PaginationState> = old => {
let newState = functionalUpdate(updater, old)
return newState
}
return table.options.onPaginationChange?.(safeUpdater)
},
GitHub Source
Using the updater
function within a Redux action can be challenging and may not be straightforward. Redux reducers act as their own updaters, and actions should handle raw data.
It's important to consider whether storing this data in Redux truly makes sense. There are potential workarounds, albeit with limitations.
- You can maintain the pagination state within the component and synchronize changes back to Redux using a
useEffect
hook. However, this method only facilitates one-way syncing and may not accommodate changes from other actions affecting the Redux pagination state.
const reduxPagination = useSelector((state) => state.counter.pagination);
const [pagination, setPagination] = React.useState(reduxPagination);
const { pageIndex, pageSize } = pagination;
const dispatch = useDispatch();
useEffect(() => {
dispatch(browseItemModalActions.setPagination(pagination));
}, [pagination, dispatch]);
onPaginationChange: setPagination,
- An alternative approach involves applying the updater to the previously selected state from Redux and then dispatching the updated value.
const pagination = useSelector((state) => state.counter.pagination);
const dispatch = useDispatch();
const table = useReactTable({
state: {
pagination
},
onPaginationChange: (updater) => {
const nextState = updater(pagination);
dispatch(browseItemModalActions.setPagination(nextState));
},
manualPagination: true,
...
However, confusion arises when encountering a TypeScript error indicating that updater
could potentially be either a function or a value. Despite our examination of the source code confirming it to always be a function, this inconsistency raises uncertainty regarding whether the react-table
callback should indeed accept plain data values.