Describe the bug
Table Options API state.selectedRowPaths: Set<RowPathKey> does not work.
My goal is to provide selection through parent component (making react-table controlled)
but internal state override is not taken into account.
To Reproduce
Expected behavior
When provided, Table Options API state should override internal state.
Desktop (please complete the following information):
Additional context
BETA react-table 26
Docs need to be updated still. You can now use the reducer option to override state. I’ll add docs later today.
Tanner Linsley
On Dec 4, 2019, 5:03 AM -0500, Alexis FR notifications@github.com, wrote:
Describe the bug
Table Options API state.selectedRowPaths: Setdoes not work.
My goal is to provide selection through parent component (making react-table controlled)
but internal state override is not taken into account.
To Reproduce
- Go to https://codesandbox.io/s/unruffled-perlman-8bztx
- Initial state is OK (5th row is selected)
- State override is NOK (3th row not selected)
Expected behavior
When provided, Table Options API state should override internal state.
Desktop (please complete the following information):• OS : Windows
• Browser : Chrome
• Version : 78Additional context
BETA react-table 26
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or unsubscribe.
I am facing a somewhat related issue.
In my implementation, I had a "toggle all" button which would collapse/expand all table groups simultaneously. In beta.1 version I implemented it with the help of useTableState hook:
// setTableState is the second element returned by useTableState hook
setTableState(actualState => ({
...actualState,`
expanded: isAlreadyExpanded ? [] : getAllExpandedState(rows) // this function collects paths of all rows that should be expanded
}), ReactTable.actions["toggleExpanded"]);
Now that table state hook is deprecated and there is no toggleExpanded action, I'm trying to implement it with a dispatcher, like this:
dispatch({
type: ReactTable.actions.toggleExpandedByPath,
path: [],
expanded: isAlreadyExpanded ? [] : getAllExpandedState(rows)
});
But it doesn't work, probably because toggleExpandedByPath action now requires path parameter. What should I pass to the path parameter if I want to toggle rows in bulk, not one-by-one?
I would appreciate if you help me here, or point me to the right place in the documentation, @tannerlinsley
Hmm, now that you're bringing up this use case, I am starting to wonder if a state override api is worth going back to. The reducer pattern clears up a lot of stuff with the state internally, but what you're talking about is "controlling" the final state (and it would need to be able to be memoized). I'll noodle on this a bit and get back to you.
How does this look? (This is a snippet from the docs I'm writing):
Occasionally, you may need to override some of the table state from a parent component or from somewhere above the usage of useTable. In this case, you can turn to useTable's useControlledState option. This hook function is run on every render and allows you an opportunity to override or change the final table state in a safe way.
For example, to control a table's pageIndex from a parent component:
const [controlledPageIndex, setControlledPage] = React.useState(0)
useTable({
useControlledState: state => {
return React.useMemo(
() => ({
...state,
pageIndex: controlledPageIndex,
}),
[state, controlledPageIndex]
)
},
})
It's important that the state override is done within a useMemo call to prevent the state variable from changing on every render.
This looks like a similar problem i'm having trying to drive state from react-router. Getting table state into history works cleanly, but pushing it back in when the user his the back button has been problematic. I currently push the 'state' option in with a memoized value, this works for pageIndex, but does not seem to work with sortBy.
The above solution appears workable and very close to what I am already doing.
Awesome I think it’s worth shipping and trying out then.
This is now available in beta.27
Thank you @tannerlinsley , it is a solution.
But it means that now I have to take full control over the expanded state of the rows, doesn't it? Previously I could overwrite the array of expanded rows only when needed, i.e. when a user clicked "expand all / collapse all" button. Now I also need to update controlled expanded state when the user clicks on any individual expandable row.
So generic API is available, and that's the most important. But for this particular use-case, which might be quite common (just like select all / unselect all functionality), wouldn't it be nice to have a special action? Or to update semantics of ReactTable.actions.toggleExpandedByPath action to allow for a bulk update? All in all, in beta.1 I could do this using ReactTable.actions.toggleExpanded action
Thanks !
It was this kind of API I was looking for to tune the state.
I tested it successfully for my use case.
A remark : useMemo cannot be used (as described above) in useControlledState because it will "block/memoize" the internal state as long as hooks dependencies does not change.
So if controlledPageIndex does not change, internal state will be kept as is forever...
Something like that will work :
useTable({
useControlledState: state => {
if (state.pageIndex !== controlledPageIndex) {
return { ...state, pageIndex: controlledPageIndex };
}
return state;
},
})
Ah yes, you are correct. But you can simply add state to the memoization dependencies.
@afrz have you figured out how to control selection through a parent component? It would be great if there was an example for this.
@serge20 have you tried example given in FAQ ?
Below a constricted sample working in latest version RC15.
//in parent component
const controlledSelectedRowIds = {
"id-A": true,
"id-B": true
}
//in table definition
useTable({
useControlledState: state => {
if (Object.keys(controlledSelectedRowIds).length > 0)
return { ...state, selectedRowIds: controlledSelectedRowIds };
return state;
},
})
In addition, you should use your own select handlers (in your custom table) to maintain selected rows state in your parent component (to update _controlledSelectedRowIds_ in above example) and not use handlers (toggleRowSelected...) provided by the useRowSelect hook.
Most helpful comment
This is now available in beta.27