fix: [DHIS2-21580] Sequential errors are not shown in the FeedbackBar#4591
fix: [DHIS2-21580] Sequential errors are not shown in the FeedbackBar#4591henrikmv wants to merge 14 commits into
Conversation
…e-optimistic-enrollment-note-in-state
…nrollmentNote and WidgetEventNote components
| variant, | ||
| }; | ||
| } | ||
| const addErrorFeedback = (input: ErrorFeedbackInput) => [getErrorFeedback(input)]; |
There was a problem hiding this comment.
📝 Info: Behavioral change: feedback queue replaced with single-item replacement
The old addErrorFeedback accumulated items via [...state, newItem], forming a FIFO queue where CLOSE_FEEDBACK would shift items to reveal the next. The new version (feedback.reducerDescriptionGetter.ts:57) always returns [singleItem], discarding any existing feedback. This is actually a sensible fix because the old queue was never properly drained — AlertBar-type feedbacks had no mechanism to dispatch CLOSE_FEEDBACK (no onHidden was wired up), so the queue grew indefinitely while only feedbacks[0] was ever displayed. The new approach pairs correctly with the onHidden={onClose} addition.
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
The replacement behaviour is intentional.
The 5000ms auto-dismiss only applies to non-critical AlertBars- DHIS2 UI's AlertBar requires the user to manually close critical alerts. With the old queue, when multiple errors fired, users had to dismiss each stale message one by one.
Replacing instead of appending means the user sees the most recent, most actionable error - not a backlog of errors.
…T_VIEW_INIT_ERROR
|
| <AlertStack> | ||
| {isAlertBarOpen && ( | ||
| <AlertBar {...alertVariant} duration={5000}> | ||
| <AlertBar key={id} {...alertVariant} duration={5000} onHidden={onClose}> |
There was a problem hiding this comment.
🚩 Potential race condition between onHidden and new feedback arriving
The new onHidden={onClose} on the AlertBar (FeedbackBar.component.tsx:36) dispatches CLOSE_FEEDBACK when the alert finishes hiding. If a new error arrives while an old AlertBar is mid-hide-animation (timer expired but onHidden not yet called), the key change causes React to unmount the old AlertBar and mount a new one. If the old AlertBar's onHidden fires during or after unmount, it would dispatch CLOSE_FEEDBACK and shift the NEW error off the state at feedback.reducerDescriptionGetter.ts:61-64, causing the new error to disappear immediately. This depends on whether dhis2/ui's AlertBar properly cancels its hide callback on unmount. Standard React cleanup patterns should prevent this, but it's worth verifying with the AlertBar implementation.
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
Verified against @dhis2-ui/alert's AlertBar: its useEffect returns clearAllTimeouts as cleanup, so a key change unmounts the old bar and synchronously clears the pending hideTimeout before remove() (which calls onHidden) can fire. The race isn't reachable — remove() is purely synchronous and JS is single-threaded, so onHidden cannot fire after unmount.



DHIS2-21580
This PR fixes feedback alert behavior by:
id(viauuid()) to each feedback item, used as thekeyonAlertBarso React re-mounts the component when a new feedback arrives (resetting the auto-hide timer).onHiddentoAlertBarso it properly closes after the duration.[...state, newFeedback]) with a single-item array ([newFeedback]), meaning only the latest feedback is ever shown.The reducer helpers are refactored so
addErrorFeedbackno longer takesstateand always returns a fresh single-element array.