System:
OS: macOS 10.15.6
CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
Memory: 195.26 MB / 16.00 GB
Shell: 5.7.1 - /bin/zsh
Binaries:
Node: 12.18.0 - ~/.nvm/versions/node/v12.18.0/bin/node
Yarn: 1.22.4 - /usr/local/bin/yarn
npm: 6.14.4 - ~/.nvm/versions/node/v12.18.0/bin/npm
Watchman: 4.9.0 - /usr/local/bin/watchman
Managers:
CocoaPods: 1.9.1 - /usr/local/bin/pod
SDKs:
iOS SDK:
Platforms: iOS 13.6, DriverKit 19.0, macOS 10.15, tvOS 13.4, watchOS 6.2
Android SDK:
API Levels: 23, 28, 29
Build Tools: 28.0.3, 29.0.3
System Images: android-18 | Google APIs ARM EABI v7a, android-27 | Google APIs Intel x86 Atom, android-27 | Google Play Intel x86 Atom, android-28 | Google Play Intel x86 Atom
Android NDK: Not Found
IDEs:
Android Studio: 3.6 AI-192.7142.36.36.6392135
Xcode: 11.6/11E708 - /usr/bin/xcodebuild
Languages:
Java: 1.8.0_242 - /usr/bin/javac
Python: 2.7.16 - /usr/bin/python
npmPackages:
@react-native-community/cli: Not Found
react: 16.11.0 => 16.11.0
react-native: 0.62.0 => 0.62.0
npmGlobalPackages:
react-native: Not Found
Android only
Android 9 (sim) and 8.1 (physical)
"@react-native-community/datetimepicker": "2.6.1",
"react-native": "0.62.0",
"react-native-modal-datetime-picker": "8.7.1",
When the parent container re-renders it clears the selected date. Also after closing the modal it sometimes re-renders.
Ive had a look at the android code, it looks like the date is not being stored in state which is causing the issue with clearing. There may well be something similar with it re-rendering the modal after selecting a date. Also you are using pureComponent, even though you keep state.
const [isDatePickerVisible, setIsDatePickerVisible] = useState(true);
const [date, setDate] = useState(new Date());
const [tick, setTick] = useState(1);
useEffect(()=>{
const ticker = setInterval(()=> setTick(tick +1), 1000);
return ()=> clearInterval(ticker);
}, [])
return (
<DateTimePickerModal
isVisible
mode="date"
date={date}
onConfirm={(date) => {
setIsDatePickerVisible(false);
setDate(date);
}}
onCancel={() => setIsDatePickerVisible(false)}
/>
)
Hey @lukemcgregor , thanks for reporting the issue.
When the parent container re-renders it clears the selected date.
What do you mean by "clear the selected date"? Keeping the date in the state is a responsibility of your own component, the Android implementation here is just a wrapper of the community-datetimepicker.
Also after closing the modal it sometimes re-renders.
Probably related to https://github.com/mmazzarolo/react-native-modal-datetime-picker#the-picker-shows-up-twice-on-android
Also you are using pureComponent, even though you keep state.
Whops, nice catch. That's probably a leftover from the previous version. PRs are welcome 馃憤
So if I open the picker and click a date (say a week ago), and leave the picker open for a few seconds (eg through a re-render of the parent) the date in the picker goes back to the current days date without me touching anything. On iOS everything seems to work as expected, this is exclusively in the android component.
I think the issue is due to the state for currentDate within the component being stored on this (rather than in state), it could also be interacting with pureComponent and some kind of optimisation to completely redraw rather than keeping the existing component in memory (thus binning this).
I have been playing round with the code but its weekend for me now, ill take another look on monday.
Ok i spent some time digging into this. I think the issue is actually with @react-native-community/datetimepicker. There are a couple of issues, firstly onChange is only called when someone taps ok. This means that the value you are tracking wont get updated (and you will retain the old one as props), when the component re-renders it calls the native modal open again (with the old value).
Ive added some comments to the other library, hopefully this gets fixed there soon.
As part of debugging I rewrote the component using hooks, if you want I can PR it, but it hasn't resolved the issue.
Ok I've come a bit further, now I have a fix to the issue, I've memo'd the component to prevent unnecessary re-rendering, this means that it will only re-render the DateTimePicker if the date changes, which means that it isn't going to try to render that component with a date that has been superseded by the childs internal state. (see PR)
Thanks for taking the time to investigate the issue @lukemcgregor 馃憤
:tada: This issue has been resolved in version 8.8.0 :tada:
The release is available on:
Your semantic-release bot :package::rocket:
I'm still having this problem when trying to render with mode "datetime" on android. After clicking "ok", updating the date and setting isVisible to false, the android time component for stays visible.
"@react-native-community/datetimepicker": "2.4.0",
"react-native": "https://github.com/expo/react-native/archive/sdk-38.0.2.tar.gz", //based on 0.62
"react-native-modal-datetime-picker": "^8.9.1",
After adding some console.logs I noticed that when clicking ok on the date modal, two time modals are created.
Edited
I was able to fix the problem on my side by replacing both setState functions (added on #453):
const [currentDate, setCurrentDate] = useState(date);
const [currentMode, setCurrentMode] = useState(null);
replaced with
const [state, setState] = useState({
currentDate: date,
currentMode: null,
});
...and related setCurrentMode/setCurrentDate -> setState changes
Are you sure that actually fixed the problem? the usage of useState multiple times is correct
@dmdmd I can reproduce the issue, looking for a fix
@dmdmd wanna try #465 ?
you can install it with: yarn add "mmazzarolo/react-native-modal-datetime-picker#465/head"
@mmazzarolo your PR worked for me. I reverted my patch, tested with version ^8.9.2 and reproduced the problem just to be sure.
I also have no idea why my previous solution appeared to work.
Cheers!
@dmdmd your previous solution worked because you were updating the state once instead of twice (and doing it twice causes https://github.com/mmazzarolo/react-native-modal-datetime-picker#the-picker-shows-up-twice-on-android)
thanks for testing it :)