Is it possible to reconcile React DOM nodes by a globally-unique identifier?

Viewed 36

This is more of a conceptual question than a specific implementation question.

The React documentation talks about lists & keys and how the key of an item can be used to reconcile a DOM element. My understanding is that in React DOM, the reconciliation system is able to avoid re-rendering a DOM node by caching the results of child renders by key and re-using them if the key has not changed.

This works great for flat lists.

My application is a deeply-recursive structure editor that makes heavy use of SVG elements to make a visual representation of a tree-shaped data structure (a node can easily contain a hundred or more other nodes), and each node type is generally represented by a component.

A fundamental operation in this data structure is to remove a node from the tree (detach) and then subsequently insert it into a compatible "port" elsewhere in the tree (attach). Unfortunately, because the tree is so deep, rendering a node can be expensive enough that detaching or attaching a large node is visibly slow and janky when the component is forced to re-render. The rendered SVG node is the same for a given node regardless of its parent (it won't appear visually any differently). Ordinary reconciliation can't help with this because the node is not being rendered as a child of the same component, but the DOM node shouldn't need to be re-rendered. The best solution would be if the action of replacing the "port" component with the new node could be reconciled to a simple DOM operation. No node has to "know" anything about its position in the tree. Parent relationships are tracked externally.

Each node has a globally-unique identifier (a unique symbol), so I'm wondering if it's possible to cache a DOM element reference by its unique ID and manually mount it into the new spot in the tree, only re-rendering the component if it subsequently changes (just as if it were a large list of components and I had given them all unique key properties). Conceptually, what I want to do is take the "detached" component and attach it as a child of another parent component in the data structure without re-rendering the child component (the parent may have to re-render because it may change to suit it's children, but the child does not change to suit its parent).

Is something like this possible without writing a custom renderer? This is only a performance concern as the application works fine other than what seems like a few hundred milliseconds of jank when attaching and detaching large nodes.

0 Answers
Related