Controlled row expand is broken
See original GitHub issueI’m fighting now for quite some time with a controlled BaseTable and found it not behaving correctly.
Side note: your example here: https://autodesk.github.io/react-base-table/examples/expand-controlled doesn’t expand/collapse nodes, but that’s probably due to no explicit handling. That’s a bit odd, given that this example is supposed to show how to manually handle the row expansion state.
Now to the issue: in my react component I use a tree which is prefilled with a number of nodes (2 levels). The third level shall be added once a second level node is expanded. I added a dummy (loading…) node to show the expansion triangle.
Now I have two approaches to make this work without success:
- Row expansion is tracked in
onExpandedRowsChanged
, which works:
private handleExpandedRowsChanged = (expandedRowKeys: RowKey[]): void => {
this.setState({ expanded: expandedRowKeys });
};
Now when I add new child nodes on first expand of a second level node (in onRowExpand
) these new children are not displayed. Instead the dummy node is still visible. I triple checked my render method is called after loading the new child nodes and the data is correctly passed to the BaseTable. So it’s not a data or refresh issue on my side.
- The second approach doesn’t use
onExpandedRowsChanged
at all, but sets the expanded state inonRowExpand
. This however has the odd outcome that the rows are not updated at all. The expansion triangle toggles as it should, but the nodes show up in the same state as before. That’s independent of whether I load new children or not.
I can somewhat make it work by using the first appraoch but when I loaded the children I add the (already expanded) rowKey again to the expanded list. It’s there twice after that, but at least it causes the table to refresh. This causes the next collapse call to be ignored however (because of the double key), which I fix by removing that key afterwards unconditionally:
// Getting the tree to re-render new children we have to use a pretty odd approach.
const { expanded } = this.state;
// First add the expanded row to the expanded state (it's already there, but do it again).
this.setState({ expanded: [...expanded, args.rowKey] });
// Then remove the duplicate row key again, to enable the next click to collapse the node
// (or it will take 2 clicks).
this.setState({ expanded });
So in sum it looks as if the internal refresh is broken completely when it comes to row expand/collapse. Also neither forceUpdate()
nor forceUpdateTable()
made any difference.
Issue Analytics
- State:
- Created 3 years ago
- Comments:7
Top GitHub Comments
In practice we use
seamless-immutable
to enforce immutable mutation, so it’s a must to change the whole object, perhaps something likeimmer
would help for you case,rowIndex
would help as it represents the position of current expanded data in the table, so you can find the locate the node to change in O(1), that’stableRef.getExpandedState().expandedData[rowIndex]
, no matter how deep the node is, it will be in the root level if it’s shown in the table, so actually you can always set the nextdata
with updatedexpandedData
About mutation of objects: that’s a rather strange idea, given that the entire data is an object. The question is: where do we draw the line what is checked for changes. The tree data is an object with children, which in turn are also objects which children. There’s no single line to say: “here’s the last checked point, anything below is considered being part of that object, which hence must be replaced as a whole”.
When I have an object with a child array then any optimization should always check if the child array has changed, no? You certainly do the check recursively for lower level elements, why not also checking if the children member as such changed?
And for the row index: that doesn’t help at all. I have a tree stucture in memory, not a row list. But since I have not thousands of nodes, doing a linear depth-first search for the row key shouldn’t take that long. It’s just that I feel this is the wrong approach.
Anyway, many thanks for that great component and your effort to help me with my problems!