…work#7471)
This commit fixes the drag-and-drop reordering functionality for repeatable
fields that use internal React state (DateTime, Currency, NumberField).
Root Cause:
-----------
When users drag-and-drop to reorder repeatable field values, the parent
component calls arrayMove() to reorder the values array. However, field
components like DateTime maintain internal state (localStringValue,
localMomentValue) that was initialized once via useState() and never
updated when the external 'value' prop changed.
Additionally, React was reusing the same component instances because the
key prop was based solely on position index (fieldConfig.name-index),
causing stale internal state to persist even as values swapped positions.
Solution:
---------
1. Added useEffect hooks to sync internal state with external value prop
changes in DateTime, Currency, and NumberField components.
2. Changed the React key in RepeatableFieldList to include the actual
value (fieldConfig.name-JSON.stringify(valueItem)-index), forcing
React to remount components when values change positions.
Affected Files:
- ui/js/dfv/src/components/field-wrapper/repeatable-field-list.js
- ui/js/dfv/src/fields/datetime/index.js
- ui/js/dfv/src/fields/currency/index.js
- ui/js/dfv/src/fields/number-field/index.js
Fixes pods-framework#7471
Summary
Fixes the inability to reorder repeatable date/time field values via drag-and-drop in the admin UI.
Closes #7471
🔍 Root Cause Analysis
When users drag-and-drop to reorder repeatable field values, the following chain of events occurs:
handleDragEnd()inRepeatableFieldListcallsarrayMove()to reorder thevaluesArraysetFullValue()updates the parent state, triggering a re-renderSubfieldWrapperreceives a newvalueprop at its positionWhy It Didn't Work for Date/Time Fields
Problem 1: Stale Internal State
Fields like
DateTime,Currency, andNumberFieldmaintain internal React state for formatted display values:The
useStateinitializer function only runs on first render. When thevalueprop changed after a drag-drop reorder, the internal state remained stale because there was no mechanism to sync it.Problem 2: Position-Based React Keys
When items reorder:
["2024-01-01", "2024-02-02"]→ Keys:["field-0", "field-1"]["2024-02-02", "2024-01-01"]→ Keys:["field-0", "field-1"](unchanged!)React sees the same keys and reuses the same component instances, just passing new props. For simple text inputs this works fine (they directly use
valueprop), but for DateTime the stale internal state causes the display to "snap back" to old values.✅ Solution
Fix 1: Added
useEffectto Sync State with PropsBefore:
After:
Fix 2: Changed React Key to Include Value
Before:
After:
By including the value in the key, React treats components as different when their values change positions, forcing a proper remount with fresh state initialization.
📁 Files Changed
ui/js/dfv/src/components/field-wrapper/repeatable-field-list.jsui/js/dfv/src/fields/datetime/index.jsuseEffectto sync internal stateui/js/dfv/src/fields/currency/index.jsuseEffectto sync internal stateui/js/dfv/src/fields/number-field/index.jsuseEffectto sync internal state🧪 Testing
Automated
Manual Testing Steps
Also tested with repeatable Currency and Number fields.
📦 Test Build
pods-fix-7471.zip
Screen recording
https://videos.faisalahammad.com/recordings/c8bJrtegcX4p7bWJBOfH