mmazzarolo / react-native-modal-datetime-picker

A React-Native datetime-picker for Android and iOS
MIT License
2.98k stars 399 forks source link

App freeze when used with `@gorhom/bottom-sheet` #676

Open shop-fluencer opened 1 year ago

shop-fluencer commented 1 year ago

Environment

expo-env-info 1.0.5 environment info: System: OS: Windows 10 10.0.19044 Binaries: Node: 16.13.2 - C:\Program Files\nodejs\node.EXE Yarn: 1.22.11 - ~\AppData\Roaming\npm\yarn.CMD npm: 8.1.2 - C:\Program Files\nodejs\npm.CMD IDEs: Android Studio: Version 2020.3.0.0 AI-203.7717.56.2031.7583922 npmPackages: expo: ^47.0.0 => 47.0.8 react: 18.1.0 => 18.1.0 react-dom: 18.1.0 => 18.1.0 react-native: 0.70.5 => 0.70.5 react-native-web: ~0.18.7 => 0.18.8 Expo Workflow: managed

Platforms

iOS Phone

Versions

Description

Why my app freeze on iOS when I want to show the calendar ? sometimes work, sometimes its freezing. I have to restart my app...

This worked fine after upgrading expo from 46 to 47

€: Happens when I have modal. When I dont have a modal its work...

Reproducible Demo

const ModalProductRelease = forwardRef<BottomSheetModal, IModalProductRelease>(({ onPress, onDelete }, ref) => {
  const { t } = useTranslation();

  const [release, setRelease] = useState<IProductRelease | null>({
    date: null,
    time: null
  });

  // Datepicker
  const [isCreated, setIsCreated] = useState<boolean>(false);
  const [isDatePickerVisible, setDatePickerVisibility] = useState(false);

  const hideDatePicker = () => setDatePickerVisibility(false);

  const [mode, setMode] = useState<'date' | 'time'>('date');

  const showDatePicker = ({ mode }: { mode: 'date' | 'time' }) => (setMode(mode), setDatePickerVisibility(true));

  const snapPoints = useMemo(() => ['25%', isCreated ? 380 : 340], [isCreated]);

  const handleConfirm = (date: Date) => {
    if(mode === 'date') {
      setRelease(prev => ({
        ...prev,
        date,
        time: prev.time
      }));
    } else {
      setRelease(prev => ({
        ...prev,
        date: prev.date,
        time: date
      }));
    }
    hideDatePicker();
  };

  const handleFinishRelease = () => {
    if(release.date === null || release.time === null) {
      setModalMessage({open: true, message: 'Bitte fülle das Datum aus.'})
    } else {
      setIsCreated(true);
      onPress(release);
    }
  };

  const handleRemoveRelease = () => (setRelease({date: null, time: null}), onDelete(), setIsCreated(false), Toast.show({
    type: 'success',
    position: 'bottom',
    text1: 'Erfolgreich gelöscht!',
    text2: 'Dein Release wurde gelöscht.',
    visibilityTime: 4000,
    autoHide: true,
    topOffset: 20,
    bottomOffset: 40,
    onPress: () => Toast.hide()
  }));
  return (
    <BottomSheetModal
      ref={ref}         
      index={1}
      snapPoints={snapPoints}
      keyboardBehavior='interactive'
      keyboardBlurBehavior='restore'
      stackBehavior='push'
      handleIndicatorStyle={[s.handleStyle, s.handleColorWhite]}
      backdropComponent={BottomSheetBackdrop}
    >
      <View style={s.paddingH}>
        <View style={s.btnContainer}>
          <Pressable onPress={() => showDatePicker({mode: 'date'})} style={[ButtonStyles.full_without, s.btnHalf]}>
            <Text style={s.btnTextNormal}>{ release.date !== null ? t('register.step2.birthday', { date: release.date }) : 'Datum auswählen' }</Text>
          </Pressable>
          <Pressable onPress={() => showDatePicker({mode: 'time'})} style={[ButtonStyles.full_without, s.btnHalf]}>
            <Text style={s.btnTextNormal}>{ release.time !== null ? t('modal_coupon.date', { date: release.time }) : 'Uhrzeit auswählen' }</Text>
          </Pressable>
        </View>

        <DateTimePickerModal
          isVisible={isDatePickerVisible}
          mode={mode}
          onConfirm={handleConfirm}
          onCancel={hideDatePicker}
        />

        { isCreated &&
          <View style={[s.centered, s.removeBtn]}>
            <Pressable onPress={handleRemoveRelease}>
              <Text style={s.titleBtnText}>Veröffentlichung entfernen</Text>
            </Pressable>
          </View>
        }

        <View style={s.containerInner}>
          <Pressable onPress={handleFinishRelease} style={[ButtonStyles.full]}>
            <Text style={s.btnText}>Fertig</Text>
          </Pressable>
        </View>
      </View>
    </BottomSheetModal>
  )
});
738 commented 1 year ago

When I use this library with BottomSheetModal of @gorhom/bottom-sheet, I encountered same freezing issue intermittently.

danielmark0116 commented 1 year ago

Hi, just writing a small FIY for anyone having a similar issue with modals freezing (it was a freeze in my case, not a crash) the app on iOS.

In my case it was happening only on release type of builds.

What was causing the issue was the animated bar component (simple line that was being animated over time). Basically the bar was representing a countdown and the modal could be opened during the animation.

The line had width property animated with reanimated (v2). After changing the animation to target translateX in place of width, the problem disappeared :)

bradherman commented 1 year ago

Also experiencing this... Also use @gorham/bottom-sheet throughout app

geydson commented 1 year ago

@mmazzarolo Any solution? I'm using expo sdk 47, the screen is crashing whenever I open the IOS calendar, I'm not using @gorhom/bottom-sheet I have it installed but it's used on other screens and I also don't have any animation, like the example of a problem with reanimated, I've already updated to expo's compatible versions, but even so the problem persists, it occurs in the emulator, I haven't tested it running on the physical device yet ;/

my current environment:

expo sdk - 47 "react-native-modal-datetime-picker" : "14.0.1" "@react-native-community/datetimepicker": "6.5.2"

alicja-mruk commented 1 year ago

I experience the same issue also using @gorham/bottom-sheet

However, when I moved the DateTimePicker outside of the bottom sheet modal, it seems to fix the problem

NKANGIJAFARI commented 1 year ago

Am experinencing the same issue but I uninstalled @gorhom/bottom-sheet, but the issue has persisted upto no. The freeze is not always, it can work for like 5 times and freeze and works after reloading.

"expo": "^48.0.0", "react-native-modal-datetime-picker": "^15.0.0", "@react-native-community/datetimepicker": "6.7.3",

import React, { useState } from 'react';
import { View, StyleSheet, Text, Pressable } from 'react-native';
import DateTimePickerModal from 'react-native-modal-datetime-picker';
import { Colors, Fonts } from '../../utils/constant/styles';

const DateTimePickerComp = ({ serviceType, pickupDate, pickupTime, handleDate, handleTime }) => {
  const [isDatePickerVisible, setDatePickerVisibility] = useState(false);

  const [pickerMode, setPickerMode] = useState('');

  const showDatePicker = () => {
    setTimeout(() => setDatePickerVisibility(true), 200);
  };

  const hideDatePicker = () => {
    setTimeout(() => setDatePickerVisibility(false), 100);
  };

  const handleConfirm = (date) => {
    if (pickerMode === 'date') {
      handleDate({ value: date, error: '' });
    } else {
      handleTime({ value: date, error: '' });
    }
    hideDatePicker();
  };

  return (
    <>
      <DateTimePickerModal
        isVisible={isDatePickerVisible}
        mode={pickerMode}
        onConfirm={handleConfirm}
        onCancel={hideDatePicker}
        onHide={() => hideDatePicker}
        date={new Date()}
      />

      <View style={styles.bookingFormRow}>
        <View style={[styles.combineInput]}>
          <View style={styles.dateOrTimePressable}>
            <Text style={styles.labelStyle}>
              {serviceType === 'pick' ? 'Pickup Date' : 'Drop Off Date'}
            </Text>
            <Pressable
              onPressIn={() => {
                setPickerMode('date');
                showDatePicker();
              }}
              style={[
                styles.inputContainerStyle,
                {
                  borderColor: pickupDate?.error !== '' ? Colors.RED : Colors.darkGray,
                  borderWidth: pickupDate?.error !== '' ? 2 : 1,
                },
              ]}
            >
              <View>
                <Text>{pickupDate?.value === '' ? '  YYYY-MM-DD' : pickupDate?.value}</Text>
              </View>
            </Pressable>

            <View>
              {pickupDate?.error !== '' && (
                <Text style={styles.errorText}>{pickupDate?.error}</Text>
              )}
            </View>
          </View>

          <View style={styles.dateOrTimePressable}>
            <Text style={styles.labelStyle}>
              {serviceType === 'pick' ? 'Pickup Time' : 'Drop Off Time'}
            </Text>

            <Pressable
              Pressable
              onPressIn={() => {
                setPickerMode('time');
                showDatePicker();
              }}
              style={[
                styles.inputContainerStyle,
                {
                  borderColor: pickupTime?.error !== '' ? Colors.RED : Colors.darkGray,
                  borderWidth: pickupTime?.error !== '' ? 1 : 1,
                },
              ]}
            >
              <View>
                <Text>{pickupTime?.value === '' ? '  hr : min' : pickupTime?.value}</Text>
              </View>
            </Pressable>

            <View>
              {pickupDate?.error !== '' && (
                <Text style={styles.errorText}>{pickupTime?.error}</Text>
              )}
            </View>
          </View>
        </View>
      </View>
    </>
  );
};

export default DateTimePickerComp;
const styles = StyleSheet.create({
  bookingFormRow: {
    width: '100%',
    marginTop: 20,
  },
  labelStyle: {
    ...Fonts.grayRegular,
    fontSize: 12,
    position: 'absolute',
    top: '-20%',
    left: 10,
    backgroundColor: 'white',
    paddingHorizontal: 3,
    zIndex: 10,
  },

  inputContainerStyle: {
    backgroundColor: 'white',
    borderRadius: 10,
    borderWidth: 1,
    borderColor: 'grey',
    height: 45,
    flexDirection: 'row',
    alignItems: 'center',
    width: '100%',
    paddingHorizontal: 15,
  },

  errorText: { color: Colors.RED, fontSize: 12 },

  combineInput: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    width: '100%',
  },

  dateOrTimePressable: { width: '47%' },

  label: { color: Colors.BLACK, ...Fonts.black12Regular },

  row: { backgroundColor: 'red' },
});
guss189 commented 1 year ago

Did you find a solution ? I'm completely stuck with this problem

NKANGIJAFARI commented 1 year ago

@guss189 Do you have any animations in the app or a react native reanimated carousel. The carousel was my issue and I changed to build my own custom carousel.

rajavarri commented 1 year ago

I too faced the same App freeze issue in IOS while using DateTimePickerModal in a bottomsheet something like this worked for me {isDatePickerVisible && <DateTimePickerModal isVisible={isDatePickerVisible} mode={pickerMode} onConfirm={handleConfirm} onCancel={hideDatePicker} onHide={() => hideDatePicker} date={new Date()} />}

christophby commented 11 months ago

I had to remove a LayoutAnimation to fix the issue, thanks for the hint.