Skip to content

Conversation

@VictorMerk
Copy link

Fixes #338
This PR addresses significant performance lag encountered when interacting with large lists (e.g., reordering items, typing in sub-fields) in the EntryForm.

The Problem
Previously, any state update within the ListField (such as hovering, dragging, or typing) caused a "ripple effect" where every single item in the list would re-render. For lists with complex children (like the Publications or Members sections), this resulted in noticeable UI blocking and lag.

The Solution
I have implemented a standard React performance optimization strategy:

1.Component Extraction & Memoization:

  • Extracted list items into a new SortableListFieldItem component.
  • Wrapped it in React.memo so it only re-renders if its specific props (data, index, open state) change.

2.Stable Callbacks:

  • Wrapped all event handlers (toggleOpen, removeItem, handleDragEnd, etc.) in useCallback to prevent breaking memoization in child components.

3.Recursive Optimization:

  • Applied React.memo to SingleField, ObjectField, and BlocksField to ensure the benefits propagate down the component tree.

Performance Impact

  • Before: O(n) re-renders on every interaction (linear growth with list size).
  • After: O(1) or O(small_subset) re-renders for most interactions.
  • Validated via build and type checks.

Technical Notes

  • Trade-off on handleDragEnd stability: The handleDragEnd function technically updates heavily because it depends on arrayFields and fieldValues to calculate moves correctly. While this breaks strict prop stability for the DndContext, it is an intentional trade-off. We achieved the core performance win by memoizing the children (SortableListFieldItem), ensuring that even if the context updates, the hundreds of list items do not re-render unless involved in the drag operation. This provides the "80/20" optimization win without requiring complex ref/useEvent patterns.

hunvreus and others added 5 commits July 29, 2025 14:57
… callbacks

- Extracts list items into a memoized `SortableListFieldItem` component to prevent unnecessary re-renders of the entire list during interactions.
- Wraps `SingleField`, `BlocksField`, and `ObjectField` in `React.memo`.
- Implements `useCallback` for `toggleOpen`, `handleDragEnd`, `addItem`, `removeItem`, and `toggleAll` to ensure stable function references.
- Significantly improves performance for large lists and complex forms.
… callbacks

- Extracts list items into a memoized `SortableListFieldItem` component to prevent unnecessary re-renders of the entire list during interactions.
- Wraps `SingleField`, `BlocksField`, and `ObjectField` in `React.memo`.
- Implements `useCallback` for `toggleOpen`, `handleDragEnd`, `addItem`, `removeItem`, and `toggleAll` to ensure stable function references.
- Significantly improves performance for large lists and complex forms.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants