Skip to content

Commit

Permalink
fix(ui-date-time-input): fix DateTimeInput displaying wrong value of …
Browse files Browse the repository at this point in the history
…its value is changed in a onChange callback

Closes: INSTUI-4406

I could only repropduce it in CodeSandbox, but according to React documentation setState is not
deterministic. Backport of PR #1829 from InstUI v10
TEST PLAN:
Make a DateTimeInput whose value changes in an onChange listerer on CodeSandbox. It should update
properly
  • Loading branch information
matyasf committed Dec 19, 2024
1 parent 7252438 commit 5cc4692
Showing 1 changed file with 11 additions and 3 deletions.
14 changes: 11 additions & 3 deletions packages/ui-date-time-input/src/DateTimeInput/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ class DateTimeInput extends Component<DateTimeInputProps, DateTimeInputState> {
event.persist()
// timeout is needed here because handleDayClick could be called in the same
// frame, and it updates calendarSelectedDate which is read in here.
window.setTimeout(() => {
setTimeout(() => {
if ((event as React.KeyboardEvent).key === 'Enter') {
// user pressed enter, use the selected value in the calendar
this.updateStateBasedOnDateInput(this.state.calendarSelectedDate, event)
Expand Down Expand Up @@ -351,7 +351,15 @@ class DateTimeInput extends Component<DateTimeInputProps, DateTimeInputState> {
newState.message = { text: text, type: 'error' }
}
if (this.areDifferentDates(this.state.iso, newState.iso)) {
this.props.onChange?.(e, newState.iso?.toISOString())
if (typeof this.props.onChange === 'function') {
const newDate = newState.iso?.toISOString()
// Timeout is needed here because users might change value in the
// onChange event lister, which might not execute properly because
// the state change is not complete
setTimeout(() => {
this.props.onChange?.(e, newDate)
}, 0)
}
}
this.setState(newState)
}
Expand All @@ -368,7 +376,7 @@ class DateTimeInput extends Component<DateTimeInputProps, DateTimeInputState> {
// happens on the target before the relatedTarget gets focus.
// The timeout gives it a moment for that to happen
if (typeof this.props.onBlur === 'function') {
window.setTimeout(() => {
setTimeout(() => {
this.props.onBlur?.(e)
}, 0)
}
Expand Down

0 comments on commit 5cc4692

Please sign in to comment.