How to update tree data structure in React state

764 Views Asked by At

I stored a tree data structure in React state and used React Table to render the tree data. As the tree data structure is complicated, I also used immer to update the state.

I created a simplified version in sandbox to demo the problem: a parent-child tree is stored in React state, a React table renders each child node as an number input box, and renders each parent node to display total of its children's value.

The tree node class looks like this:

class TreeNode {
  name: string;
  isLeaf: boolean;
  subtotal: number | null = null;
  value: number | null = null;
  children: TreeNode[] = [];

  constructor(name: string, children?: TreeNode[]) {
    this.name = name;
    this.isLeaf = !children?.length;
    if (children?.length) this.children = children;
  }
}

React table provides an Id (e.g. '0.0') for each row so that I can locate to the related child in the state, also its parent when a child is updated, and update their value / subtotal accordingly:

  const updateTableData = (rowId: string, val: number) => {
    setTableData(
      // Using immer produce
      produce((draft) => {
        // Locate updated child and parent omitted 
        ...
        if (updatedItem) {
          console.log("updatedItem is", updatedItem.name);
          updatedItem.value = val;
        }
        if (parentItem) {
          console.log("updatedItem's parent is", parentItem.name);
          parentItem.subtotal = (parentItem.subtotal ?? 0) + val;
        }
      })
    );
  };

However after the state is updated, the React table (specifically the affected cells) do not re-render to reflect the change.

I am not familiar with React table, also didn't store such complicated tree data into React state before. I am not sure if the problem is caused by React table or something else.

As I am using React table, the code looks a bit lengthy but I highlighted the key parts with comments. Many thanks for your patience and help.


Update 1

It turned out that immer does not support classes well. I updated my code following the instruction, it's re-rendering now, but still not updating the state properly.

So I updated my question title to How to update tree data structure in React state. I know it is not good idea to store complicated/nested data in React state but in my case to use the expandable feature of React table, I have to create a tree data structure.

1

There are 1 best solutions below

0
On

I ended up refactoring my code by replacing the TreeNode class with recursive traversal function, a bunch of util function and plain objects instead. With immer it's working fine and the performance is acceptable.