Skip to content

fix(dnd): add useDynamicDescription to prevent unnecessary re-renders#9738

Open
reidbarber wants to merge 2 commits intomainfrom
dnd-perf-useDynamicDescription
Open

fix(dnd): add useDynamicDescription to prevent unnecessary re-renders#9738
reidbarber wants to merge 2 commits intomainfrom
dnd-perf-useDynamicDescription

Conversation

@reidbarber
Copy link
Member

@reidbarber reidbarber commented Mar 4, 2026

Closes #2504

Adds a new useDynamicDescription hook that gets used by useDrag and useVirtualDrop.

It solves the following issue with useDescription:

  • You render a collection of 100 draggable items on the page.
  • You switch between drag modalities (e.g. go from mouse to keyboard).
  • The accessible description for the drag buttons updates from "Click to start dragging." to "Press Enter to start dragging."
  • A new node was created for that change, and the old one was removed.
  • All 100 drag buttons would re-render in order to reference that new node

Our new hook changes the text content of the existing description node, so the 100 drag buttons do not need to re-render in this case. We need to key these, so that multiple consumers can reliably share the same node.

✅ Pull Request Checklist:

  • Included link to corresponding React Spectrum GitHub Issue.
  • Added/updated unit tests and storybook for this change (for new code or code which already has tests).
  • Filled out test instructions.
  • Updated documentation (if it already exists for this component).
  • Looked at the Accessibility Practices for this feature - Aria Practices

📝 Test Instructions:

In the RAC DnD Table story, open dev tools to inspect the element.

Alternative between clicking and tabbing to switch drag modalities, and observe:

  • The description node text updates, but it's id stays the same
  • All drag button point to that description node, and don't re-render when it updates.

🧢 Your Project:

@github-actions github-actions bot added the RAC label Mar 4, 2026
@reidbarber reidbarber changed the title perf(dnd): add useDynamicDescription to prevent unnecessary re-renders fix(dnd): add useDynamicDescription to prevent unnecessary re-renders Mar 4, 2026
function getOrCreateDynamicDescriptionNode(descriptionKey: string) {
let desc = dynamicDescriptionNodes.get(descriptionKey);
if (!desc) {
let id = `react-aria-description-${descriptionId++}`;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in the case that multiple copies are loaded, this could create conflicting ids, better to use id generation like crypto.randomUUID

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or put the id generation into the hooks and make use of useId

}, [description]);

useLayoutEffect(() => {
return () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you move this up to be in the first useLayoutEffect, then you can de-duplicate the refCount removal, always handle it in the cleanup of that effect
It'll make it more readable as well because creation and cleanup associated will be right next to each other

}
}, [descriptionKey, description]);

useLayoutEffect(() => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is the purpose of this effect? i can't quite figure it out, maybe it should also be merged into the effect above?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

useDrag re-renders from useDescription

3 participants