Skip to content

Conversation

sterlingwes
Copy link

Summary

This change fixes a crash on iOS when the underlying UIDatePicker receives minimumDate > maximumDate by:

  • adding validation in JS to assert that when both are set, min must be less than max
  • updating the native fabric prop update logic to:
    • explicitly handles unsetting prior values on the underlying picker during any change before setting new ones
    • specifically handles the unset case which was handled implicitly before

This is the error that shows after this change in dev mode when this happens (before it just crashes):

Simulator Screenshot - iPhone 16 Pro - 2025-09-09 at 21 58 50
Original Crash
*** Terminating app due to uncaught exception 'NSGenericException', reason: 'Start date cannot be later in time than end date!'
*** First throw call stack:
(
	0   CoreFoundation                      0x00000001804c9690 __exceptionPreprocess + 172
	1   libobjc.A.dylib                     0x00000001800937cc objc_exception_throw + 72
	2   Foundation                          0x0000000180f55184 -[_NSConcreteDateInterval initWithStartDate:endDate:] + 396
	3   UIKitCore                           0x00000001850dfee0 -[_UIDatePickerCalendarView _reloadCalendarView] + 352
	4   UIKitCore                           0x00000001850dffa4 -[_UIDatePickerCalendarView _reload] + 48
	5   UIKitCore                           0x0000000185bfd72c -[UIDatePicker _installPickerView:updatingSize:] + 152
	6   UIKitCore                           0x0000000185bfd650 -[UIDatePicker _updatePickerViewIfNecessary] + 120
	7   ReproducerApp.debug.dylib           0x0000000107242670 -[RNDateTimePickerComponentView updatePropsForPicker:props:oldProps:

Test Plan

Reproducer used in screenshots below: https://github.com/sterlingwes/date-picker-min-max-repro

The reproducer tests the following scenarios:

Simulator Screenshot - iPhone 16 Pro - 2025-09-09 at 19 21 13
Behaviour before fixes
first second third fourth fifth
💥 Simulator Screenshot - iPhone 16 Pro - 2025-09-09 at 19 21 16 Simulator Screenshot - iPhone 16 Pro - 2025-09-09 at 19 21 34 Simulator Screenshot - iPhone 16 Pro - 2025-09-09 at 19 21 37 Simulator Screenshot - iPhone 16 Pro - 2025-09-09 at 19 21 41
Behaviour after fixes
first second third fourth fifth
Simulator Screenshot - iPhone 16 Pro - 2025-09-09 at 18 54 41 simulator_screenshot_0C99FF94-596E-4676-8D7F-E53C5D0B2FEF simulator_screenshot_D9476BAC-578E-43A8-9952-8F64F0093BB2 simulator_screenshot_5A56C3D5-C3E9-445C-9777-19868DEE9190 simulator_screenshot_AE3AAD97-42B3-4957-8BEF-23E66B455515

What's required for testing (prerequisites)?

You can either:

  • Use the example app here, which has a simple reproduction case for toggling-on min > max constraint
  • Use the reproducer

What are the steps to reproduce (after prerequisites)?

To reproduce the crash in the example app, tap the new button "set min > max (error)" then tap the picker date and it should crash. If you test on this branch that includes the changes in ios/fabric/RNDateTimePickerComponentView.mm and in src/utils.js, you should instead see the logbox error shown first above.

Compatibility

The native crash was only evident on iOS, but the JS validation approach taken here ensures the expectation is aligned across both.

Checklist

  • I have tested this on a device and a simulator
  • I added the documentation in README.md
  • I updated the typed files (TS and Flow)
  • I added a sample use of the API in the example project (example/App.js)
  • I have added automated tests, either in JS or e2e tests, as applicable
  • i did not see a reason to add docs for this as the error more clearly documents the expectation now
  • i only added js unit specs as the e2e spec tests similar things (js logbox behaviour)

}

if (oldPickerProps.maximumDate != newPickerProps.maximumDate) {
picker.maximumDate = convertJSTimeToDate(newPickerProps.maximumDate);
Copy link
Author

Choose a reason for hiding this comment

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

while my reproducer is a naive example, i believe the behaviour leading to the crash was less obvious b/c of this UIDatePicker instance re-update logic:

if a datepicker is rendered (inline on a screen or sheet for example, as is the case in the reproducer), and the component is re-rendered, the crash would occur when either minimumDate or maximumDate is updated in a way that breaks the expected constraint order (min < max) but the prior picker value for one of the props is not unset first

since these conditionals were evaluated independently this seems like the culprit, hence why I've grouped them together to validate them together

@sterlingwes
Copy link
Author

Looks like this also might fix #1008

@yonitou
Copy link

yonitou commented Sep 11, 2025

Thanks for this PR. This bug is really problematic for us since our production users are experiencing a lot of crashes in our datepickers modals/screens. Looking forward to see it merged !
Meanwhile @sterlingwes , do you think it's safe to target your PR in our package.json to use your fix asap ?

@sterlingwes
Copy link
Author

@yonitou i don't know enough about your setup or specific issue but i don't see a problem with referencing the PR. we've applied the patch but are still waiting on rolling it out to prod. personally i'd apply it as a patch to whatever version you're on since the NPM package content won't be the same as whatever you pull in from a github reference

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