Skip to content

Declarative setDate() and setToday() - feature via a patch #2718

@ajp8164

Description

@ajp8164

For anyone interested this is patch that allows the setting of a date using new functions on the CalendarProvider.

Two functions:
setDate: (date: string) => void
setToday: () => void (a convenience function)

Just create a ref on the CalendarProvider and call a function.

Using these functions I'm able to place today, left, and right arrows anywhere on my view (specifically outside the calendar component). I'm using luxon for dates.

Example:

const [current, setCurrent] = useState<ISODateString>(
  DateTime.now().toFormat('yyyy-MM-dd'),
);

...

<CalendarProvider
  ref={calRef}
  ...
/>

...

onPress={() => {
  const newDate = DateTime.fromISO(current)
    .plus({ month: 1 })
    .toISODate();
  if (newDate) {
    calRef.current?.setDate(newDate);
    setCurrent(newDate);
  }
}}

Patch:

diff --git a/node_modules/react-native-calendars/src/expandableCalendar/Context/Provider.d.ts b/node_modules/react-native-calendars/src/expandableCalendar/Context/Provider.d.ts
index 8219efa..20d1dd3 100644
--- a/node_modules/react-native-calendars/src/expandableCalendar/Context/Provider.d.ts
+++ b/node_modules/react-native-calendars/src/expandableCalendar/Context/Provider.d.ts
@@ -3,6 +3,7 @@ import { ViewStyle, ViewProps, StyleProp } from 'react-native';
 import { Theme, DateData } from '../../types';
 import { UpdateSources, CalendarNavigationTypes } from '../commons';
 export interface CalendarContextProviderProps extends ViewProps {
+    ref: RefObject<CalendarContextProviderImperativeMethods | null>;
     /** Initial date in 'yyyy-MM-dd' format. Default = now */
     date: string;
     /** Specify theme properties to override specific styles for calendar parts */
@@ -28,6 +29,10 @@ export interface CalendarContextProviderProps extends ViewProps {
     /** The left inset of the timeline calendar (sidebar width), default is 72 */
     timelineLeftInset?: number;
 }
+export interface CalendarContextProviderImperativeMethods {
+    setDate: (date: string) => void;
+    setToday: () => void;
+}; 
 /**
  * @description: Calendar context provider component
  * @example: https://github.com/wix/react-native-calendars/blob/master/example/src/screens/expandableCalendar.js
diff --git a/node_modules/react-native-calendars/src/expandableCalendar/Context/Provider.js b/node_modules/react-native-calendars/src/expandableCalendar/Context/Provider.js
index ec1e1be..f4dbc03 100644
--- a/node_modules/react-native-calendars/src/expandableCalendar/Context/Provider.js
+++ b/node_modules/react-native-calendars/src/expandableCalendar/Context/Provider.js
@@ -1,6 +1,6 @@
 import { includes } from 'lodash';
 import XDate from 'xdate';
-import React, { useRef, useState, useCallback, useMemo } from 'react';
+import React, { forwardRef, useRef, useState, useCallback, useMemo, useImperativeHandle } from 'react';
 import { View } from 'react-native';
 import { sameMonth } from '../../dateutils';
 import { xdateToData } from '../../interface';
@@ -9,11 +9,21 @@ import { UpdateSources } from '../commons';
 import styleConstructor from '../style';
 import CalendarContext from './index';
 import TodayButton from './todayButton';
+import { toMarkingFormat } from '../../interface';
 /**
  * @description: Calendar context provider component
  * @example: https://github.com/wix/react-native-calendars/blob/master/example/src/screens/expandableCalendar.js
  */
-const CalendarProvider = (props) => {
+const CalendarProvider = (props, ref) => {
+    useImperativeHandle(ref, () => ({
+        setDate: (date) => {
+            _setDate(date, UpdateSources.DAY_PRESS);
+        },
+        setToday: () => {
+            _setDate(date, UpdateSources.TODAY_PRESS);
+        }
+    }));
+
     const { theme, date, onDateChanged, onMonthChange, disableAutoDaySelection, showTodayButton = false, disabledOpacity, todayBottomMargin, todayButtonStyle, style: propsStyle, numberOfDays, timelineLeftInset = 72, children } = props;
     const style = useRef(styleConstructor(theme));
     const todayButton = useRef();
@@ -30,6 +40,10 @@ const CalendarProvider = (props) => {
             _setDate(date, UpdateSources.PROP_UPDATE);
         }
     }, [date]);
+    const getTodayDate = () => {
+        return toMarkingFormat(new XDate());
+    };
+
     const getUpdateSource = useCallback((updateSource) => {
         // NOTE: this comes to avoid breaking those how listen to the update source in onDateChanged and onMonthChange - remove on V2
         if (updateSource === UpdateSources.ARROW_PRESS || updateSource === UpdateSources.WEEK_ARROW_PRESS) {
@@ -76,5 +90,5 @@ const CalendarProvider = (props) => {
       {showTodayButton && renderTodayButton()}
     </CalendarContext.Provider>);
 };
-export default CalendarProvider;
+export default forwardRef(CalendarProvider);
 CalendarProvider.displayName = 'CalendarProvider';

Ed. this library is way out of date but seems to be the best library for the features it provides. I have many patches on my project because maintainers go missing and patching is more straightforward than forking and maintaining. This is a general comment on many RN libraries and GH capabilities. There should be a reputation based way to have any user contribute :-/

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions