react-native-ui-datepicker icon indicating copy to clipboard operation
react-native-ui-datepicker copied to clipboard

Warning: useInsertionEffect must not schedule updates.

Open getsettalk opened this issue 6 months ago • 0 comments

why showing this error while i'm using like this :

import React, { useState, useEffect } from 'react';
import { View, StyleSheet, TouchableOpacity, Text, Switch } from 'react-native';
import RBSheet from 'react-native-raw-bottom-sheet';
import DateTimePicker from 'react-native-ui-datepicker';
import DynamicIcon from '@components/global/DynamicIcon';
import dayjs from 'dayjs';

const DatePickerSheet = ({ sheetRef, theme, startDate, endDate, onDatesChange, initialMode = 'range' }) => {
  // Track the current mode (single or range)
  const [mode, setMode] = useState(initialMode);
  
  // Store date range as object with startDate and endDate
  const [dateRange, setDateRange] = useState({
    startDate: startDate ? dayjs(startDate) : null,
    endDate: endDate ? dayjs(endDate) : null
  });
  
  // Store single date for single mode
  const [singleDate, setSingleDate] = useState(startDate ? dayjs(startDate) : null);

  // Update local state when props change
  useEffect(() => {
    setDateRange({
      startDate: startDate ? dayjs(startDate) : null,
      endDate: endDate ? dayjs(endDate) : null
    });
    setSingleDate(startDate ? dayjs(startDate) : null);
  }, [startDate, endDate]);

  // Handle date range selection
  const handleRangeChange = ({ startDate, endDate }) => {
    console.log("Date range selected:", { startDate, endDate });
    setDateRange({
      startDate: startDate ? dayjs(startDate) : null,
      endDate: endDate ? dayjs(endDate) : null
    });
  };
  
  // Handle single date selection
  const handleSingleChange = ({ date }) => {
    console.log("Single date selected:", date);
    setSingleDate(date ? dayjs(date) : null);
  };

  // Apply changes and close sheet
  const handleApply = () => {
    try {
      if (mode === 'single' && singleDate) {
        // For single date, use the same date for both start and end
        const dateObj = singleDate instanceof dayjs
          ? singleDate.toDate()
          : new Date(singleDate);
        
        onDatesChange({
          startDate: dateObj,
          endDate: dateObj
        });
        sheetRef.current.close();
      } 
      else if (mode === 'range' && dateRange.startDate && dateRange.endDate) {
        // For range date
        const startDateObj = dateRange.startDate instanceof dayjs
          ? dateRange.startDate.toDate()
          : new Date(dateRange.startDate);

        const endDateObj = dateRange.endDate instanceof dayjs
          ? dateRange.endDate.toDate()
          : new Date(dateRange.endDate);

        onDatesChange({
          startDate: startDateObj,
          endDate: endDateObj
        });
        sheetRef.current.close();
      }
    } catch (error) {
      console.error("Error converting dates:", error);
      sheetRef.current.close();
    }
  };

  // Reset state when sheet opens
  const handleOpen = () => {
    setDateRange({
      startDate: startDate ? dayjs(startDate) : null,
      endDate: endDate ? dayjs(endDate) : null
    });
    setSingleDate(startDate ? dayjs(startDate) : null);
  };

  // Toggle between single and range mode
  const toggleMode = () => {
    setMode(prevMode => {
      const newMode = prevMode === 'single' ? 'range' : 'single';
      
      // When switching to single mode, use the start date as the single date
      if (newMode === 'single' && dateRange.startDate) {
        setSingleDate(dateRange.startDate);
      }
      // When switching to range mode, use the single date as both start and end dates
      else if (newMode === 'range' && singleDate) {
        setDateRange({
          startDate: singleDate,
          endDate: singleDate
        });
      }
      
      return newMode;
    });
  };

  // Check if dates are selected
  const hasSelectedDates = mode === 'single' 
    ? !!singleDate 
    : (dateRange.startDate && dateRange.endDate);

  // Format date for display, safely handling any date format
  const formatDate = (date) => {
    if (!date) return 'Select date';
    try {
      return dayjs(date).format('MMM D, YYYY');
    } catch (e) {
      console.log("Error formatting date:", e);
      return 'Invalid date';
    }
  };

  return (
    <RBSheet
      ref={sheetRef}
      height={520} // Increased height to accommodate the mode switch
      openDuration={250}
      closeDuration={200}
      onOpen={handleOpen}
      customStyles={{
        container: {
          backgroundColor: theme.surface,
          borderTopLeftRadius: 12,
          borderTopRightRadius: 12,
        },
      }}
    >
      <View style={styles.sheetContent}>
        <View style={styles.header}>
          <Text style={[styles.pickerTitle, { color: theme.text }]}>
            {mode === 'single' ? 'Select Date' : 'Select Date Range'}
          </Text>
          <TouchableOpacity
            style={styles.closeButton}
            onPress={() => sheetRef.current.close()}
          >
            <DynamicIcon
              name="close"
              size={24}
              color={theme.text}
              library="MaterialCommunityIcons"
            />
          </TouchableOpacity>
        </View>
        
        {/* Mode toggle */}
        <View style={styles.modeToggleContainer}>
          <Text style={[styles.modeText, { color: theme.text }]}>Single Date</Text>
          <Switch
            value={mode === 'range'}
            onValueChange={toggleMode}
            trackColor={{ false: theme.primaryShade1, true: theme.primaryShade1 }}
            thumbColor={mode === 'range' ? theme.success : theme.primary}
          />
          <Text style={[styles.modeText, { color: theme.text }]}>Date Range</Text>
        </View>

        {mode === 'single' ? (
          <DateTimePicker
            mode="single"
            date={singleDate}
            onChange={handleSingleChange}
            minDate={dayjs().toDate()}
            styles={{
              today_label: { color: theme.success, fontWeight: '800' },
              selected: { backgroundColor: theme.info },
              day_label: { borderRadius: 5, color: theme.text },
              button_next: { backgroundColor: theme.primary, borderRadius: 20 },
              button_prev: { backgroundColor: theme.primary, borderRadius: 20 },
              weekday_label: { color: theme.text },
              month_selector_label: { color: theme.text },
              year_selector_label: { color: theme.success },
              selected_label: { color: theme.text, fontWeight: 600 },
              disabled_label: { color: theme.errorShade2 },
              active_year: { backgroundColor: theme.successShade4 },
              active_year_label: { color: theme.text },
            }}
          />
        ) : (
          <DateTimePicker
            mode="range"
            startDate={dateRange.startDate}
            endDate={dateRange.endDate}
            onChange={handleRangeChange}
            minDate={dayjs().toDate()}
            styles={{
              today_label: { color: theme.success, fontWeight: '800' },
              selected: { backgroundColor: theme.info },
              day_label: { borderRadius: 5, color: theme.text },
              range_fill: { backgroundColor: theme.primaryShade1 },
              button_next: { backgroundColor: theme.primary, borderRadius: 20 },
              button_prev: { backgroundColor: theme.primary, borderRadius: 20 },
              weekday_label: { color: theme.text },
              month_selector_label: { color: theme.text },
              year_selector_label: { color: theme.success },
              range_end: { backgroundColor: theme.success, borderRadius: 50 },
              range_start: { backgroundColor: theme.success, borderRadius: 50, },
              range_start_label: { color: theme.text, fontWeight: 600 },
              range_end_label: { color: theme.text, fontWeight: 600 },
              disabled_label: { color: theme.errorShade2 },
              active_year: { backgroundColor: theme.successShade4 },
              active_year_label: { color: theme.text },
            }}
          />
        )}

        <View style={styles.footer}>
          <Text style={[styles.dateRangeText, { color: theme.text }]}>
            {mode === 'single' 
              ? formatDate(singleDate)
              : `${formatDate(dateRange.startDate)} - ${formatDate(dateRange.endDate)}`
            }
          </Text>
          <TouchableOpacity
            style={[
              styles.applyButton,
              (!hasSelectedDates)
                ? { backgroundColor: theme.tertiary }
                : { backgroundColor: theme.primary }
            ]}
            onPress={handleApply}
            disabled={!hasSelectedDates}
          >
            <Text style={[styles.applyButtonText, { color: theme.background }]}>Apply</Text>
          </TouchableOpacity>
        </View>
      </View>
    </RBSheet>
  );
};

const styles = StyleSheet.create({
  sheetContent: {
    flex: 1,
    padding: 20,
    position: 'relative',
  },
  header: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    marginBottom: 10,
  },
  pickerTitle: {
    fontSize: 16,
    fontWeight: '600',
  },
  closeButton: {
    padding: 5,
  },
  modeToggleContainer: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'center',
    marginBottom: 15,
  },
  modeText: {
    marginHorizontal: 8,
    fontSize: 14,
  },
  footer: {
    marginTop: 15,
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
  },
  dateRangeText: {
    fontSize: 14,
  },
  applyButton: {
    paddingVertical: 8,
    paddingHorizontal: 16,
    borderRadius: 8,
  },
  applyButtonText: {
    fontWeight: '500',
  }
});

export default React.memo(DatePickerSheet);

See here uploaded image

Image

getsettalk avatar Apr 07 '25 07:04 getsettalk