Skip to content

Tree rerender with Custom TreeDataProvider when data state changes externally #410

Open
@hrithvik123

Description

@hrithvik123

I am trying to re render the tree when the filesystem data is changed by another component and passed to the tree in props. I have implemented this Custom TreeDataProvider:

import {
  Disposable,
  TreeDataProvider,
  TreeItem,
  TreeItemIndex,
} from "react-complex-tree";
import { DirectoryWithLoadedChildren } from "../../types/fs";
import { EventEmitter } from "react-complex-tree/lib/esm/EventEmitter";

export class FSTreeDataProvider
  implements TreeDataProvider<DirectoryWithLoadedChildren>
{
  private data: Record<string, DirectoryWithLoadedChildren>;
  public treeChangeListeners: ((changedItemIds: TreeItemIndex[]) => void)[] =
    [];

  public readonly onDidChangeTreeDataEmitter = new EventEmitter<
    TreeItemIndex[]
  >();

  constructor(items: DirectoryWithLoadedChildren) {
    const newItems: Record<string, DirectoryWithLoadedChildren> = {};
    const addItems = (item: DirectoryWithLoadedChildren) => {
      newItems[item._id!] = item;
      if (item.loadedChildren) {
        item.loadedChildren.forEach(addItems);
      }
    };
    addItems(items);
    this.data = newItems;
  }

  public async getTreeItem(
    itemId: TreeItemIndex
  ): Promise<TreeItem<DirectoryWithLoadedChildren>> {
    const item = this.data[itemId as string];
    return {
      index: item._id!,
      data: item,
      isFolder: item.type === "directory",
      children: item.loadedChildren?.map((child) => child._id!) || [],
    };
  }

  public onDidChangeTreeData(
    listener: (changedItemIds: TreeItemIndex[]) => void
  ): Disposable {
    this.treeChangeListeners.push(listener);
    return {
      dispose: () =>
        this.treeChangeListeners.splice(
          this.treeChangeListeners.indexOf(listener),
          1
        ),
    };
  }
}

Here's the relevant code in the component. I am trying to emit an event in the useEffect.

const FSTreeSidebar = ({ fileSystem, onNodeClick }: FSTreeSidebar) => {
  const dataProvider = new FSTreeDataProvider(fileSystem);

  useEffect(() => {
    // console.log("File system updated:", fileSystem);
    dataProvider.onDidChangeTreeDataEmitter.emit([fileSystem._id!]);
  }, [fileSystem]);

  return (
    <>
      <UncontrolledTreeEnvironment<DirectoryWithLoadedChildren>
        dataProvider={dataProvider}
        getItemTitle={(item) => item.data.path.split("/").pop()!}
        viewState={{}}
      >
        <Tree
          treeId="tree-1"
          rootItem={fileSystem._id!}
          treeLabel="File System Tree"
        />
      </UncontrolledTreeEnvironment>
    </>
  );
};

How do I get the tree to rerender when the fileSystem data changes?

Thanks.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions