Holiday Notice: Support will be provided on a limited scale from December 24th, 2024, to January 2nd, 2025. Happy holidays and a wonderful New Year!


Topic: Buggy treeview rendering upon autocompletesearch-like filtering

doweb priority asked 2 years ago


Expected behavior Treeview that correctly renders after sorting by using data filtering

Actual behavior Treeview rerenders in a weird, partial manner upon update.

Resources (screenshots, code snippets etc.)

Here is the buggy rendering

enter image description here

Note that it persists after scrolling.

Here is the filter function:

  const filteredData = [...data].filter(function f(o: any) {
if (o.label.includes(selectedListRef.current) || selectedListRef.current === "") return true;

if (o.children) {
  return (o.children = o.children.filter(f)).length;
}
return false;

});

It's run from this:

    <MDBInput
      type="text"
      label="Søg..."
      onChange={(e) => setFieldFilter(e.target.value)}
    />

And here is the recursive function that actually puts together the tree:

  //return a recursive tree structure of JSX MDBTreeItem components
  const RecursiveTreeOuter = (e: any[], show: boolean, index: number): any => {
    return e.length !== 0 ? (
      e.map((item, itemIndex) => {
        return RecursiveTreeInner(item, show, index + itemIndex); // is itemIndex + index the right way to do this? What if there are multiple levels of nesting?
      })
    ) : (
      <></>
    );
  };
  const RecursiveTreeInner = (e: any, show: boolean, index: number): any => {
    const key = index;
    index++;
    return (
      <MDBTreeviewItem
        name={e.label}
        id={e.id}
        subtree={e.children.length !== 0}
        show={show}
        key={key}
        onClick={(el) => {
          if (e.data.type !== "") {
            props.onSelect(e, setPopoverOpen);
            if (closeOnSelect) setPopoverOpen(false);
          }
        }}
      >
        {e.children.length > 0 ? (
          RecursiveTreeOuter(e.children, show, index)
        ) : (
          <></>
        )}
      </MDBTreeviewItem>
    );
  };

State for filtering is managed here:

  const [fieldFilter, setFieldFilter] = useState("");

Likely necessary steps

So, I basically need to know how to force the component to rerender 'from scratch' based on the fact that the collection has been filtered. I have attempted to use various hooks to achieve something like this, such as useLayoutEffect, but no luck.

A workaround might be to render the component with nothing (completely bare) and then immediately after, rendering it with my dataset, perhaps only confitionally showing it after it's been rerendered. What do you recommend?

Scrolling the treeview does nothing.


Krzysztof Wilk staff commented 2 years ago

Hi!

According to the question in your code - that's probably the most straightforward method for fresh users. I think the best way to generate an ID is by using useId hook which was added in React 18 and combining them with some values (i.e. index)

I think your workaround could be good. You can also try to change some property of the treeview to rerender it - i.e. set the "selectable" option to true and to false after some milliseconds.

This problem is probably caused by the collapse component which is used in the treeview plugin - the height of expanded elements isn't calculated properly. You can try setting a height of the expanded particular collapse element to fix that temporarily.


doweb priority commented 2 years ago

Hi Krzysztof, So it's the collapse component. I had thought this might be it; that it doesn't set the height of each open element upon the re-render.

I've just tried to use the 'items' prop to set the data of the tree, but unfortunately that doesn't seem to work with the onClick event I use for selection.

Do you have any recommendation for another component I could use for displaying the treeview?

If not, you suggest setting the height of the expanded collapse element when open. This seems like a bit of a mess, as it has to be calculated at the right time - in response to the element opening. Since the calculation is already correct (eventually), what's really necessary is that the element needs to trigger the rerender of itself, and all the other elements. I'm not sure forcing a height gets around this, as I might just end up replicating the bug.


Krzysztof Wilk staff commented 2 years ago

I'm afraid there's no other workaround without our integration in the core component code. Sorry for that inconvenience.

For now, I think there shouldn't be a problem to use an MUI one or just a react-treeview.



Please insert min. 20 characters.

FREE CONSULTATION

Hire our experts to build a dedicated project. We'll analyze your business requirements, for free.

Status

Opened

Specification of the issue

  • ForumUser: Priority
  • Premium support: Yes
  • Technology: MDB React
  • MDB Version: MDB5 4.1.0
  • Device: Macbook Pro
  • Browser: Chrome
  • OS: Mac OS
  • Provided sample code: No
  • Provided link: No