react-native-calendars icon indicating copy to clipboard operation
react-native-calendars copied to clipboard

ref stopped working sometimes after version

Open Saikedo opened this issue 2 years ago β€’ 30 comments

I used to be able to pass a ref to calendar and extract some data for example like this calendarRef.current?.state.currentMonth. In the recent versions of the library, the ref just returns undefined.

Expected Behavior

Expect to be able to get the ref of the calendar

Environment

Please run these commands in the project folder and fill in their results:

react-native-calendars version: 1.1282.0 react-native version: 0.65.1

Here is some simple code that already fails to get the ref.

const calendarRef = useRef<Calendar>(null);

<Calendar
            ref={calendarRef}
            ...
/>

And we can even do something like this, and the inner ref comes back as undefined

<Calendar
            ref={ref => console.log('Ref is', ref)}
            ...
/>

Saikedo avatar Apr 11 '22 03:04 Saikedo

same problem here, seems to be caused by this commit

yiheinchai avatar Apr 11 '22 11:04 yiheinchai

Is there any solution for this, I'm also facing the above issue. I had to revert back to the old version 1.1279.0 and keep using it until this is fixed.

sajorahasan avatar Apr 12 '22 10:04 sajorahasan

Same problem

DarkB0t776 avatar Apr 20 '22 14:04 DarkB0t776

Same Problem

salihonder avatar Apr 28 '22 08:04 salihonder

Having a similar issue with trying to add a reference to AgendaList and calling agendaListRef.current.chooseDay()

KrisLau avatar May 05 '22 13:05 KrisLau

@Saikedo Hi. Why are you getting the currentMonth from the component's state and not using the onMonthChange callback?

Inbal-Tish avatar Jun 08 '22 10:06 Inbal-Tish

@KrisLau Hi. Why are you invoking chooseDay and not resetting selected prop?

Inbal-Tish avatar Jun 08 '22 10:06 Inbal-Tish

Guys, using component methods and state through ref is risky, and not a good practice. You should only do it if there is no other alternative and inform us to add the missing API so you can avoid it later. Do you have any specific ref usages that compensate for a missing API? Please specify them here and I'll try to address them.

Inbal-Tish avatar Jun 08 '22 10:06 Inbal-Tish

Guys, using component methods and state through ref is risky, and not a good practice. You should only do it if there is no other alternative and inform us to add the missing API so you can avoid it later. Do you have any specific ref usages that compensate for a missing API? Please specify them here and I'll try to address them.

I need to let the user pick a month, without having to go through a sequence, so I had implemented a month picker

import DateTimePickerModal from "react-native-modal-datetime-picker";

and then once selected I used to switch month on the calendar, by calling:

calendar.current?.updateMonth(_date);

but is not working anymore since version 1.1278.0

violabg avatar Jun 08 '22 10:06 violabg

Guys, using component methods and state through ref is risky, and not a good practice. You should only do it if there is no other alternative and inform us to add the missing API so you can avoid it later. Do you have any specific ref usages that compensate for a missing API? Please specify them here and I'll try to address them.

I need to let the user pick a month, without having to go through a sequence, so I had implemented a month picker

import DateTimePickerModal from "react-native-modal-datetime-picker";

and then once selected I used to switch month on the calendar, by calling:

calendar.current?.updateMonth(_date);

but is not working anymore since version 1.1278.0

Yes. The migration to the functional component broke the ref, which was a risky use in the first place... Anyways, why you're not resetting the date using the Calendar's initialDate prop?

Inbal-Tish avatar Jun 08 '22 10:06 Inbal-Tish

Yes. The migration to the functional component broke the ref, which was a risky use in the first place... Anyways, why you're not resetting the date using the Calendar's initialDate prop?

Thanks, is working, but I couldn't find a reference for "initialDate" in the docs, in the past I've tried to use "current" but didn't work, that's why I started to use calendar.current?.updateMonth(_date);

violabg avatar Jun 08 '22 13:06 violabg

@KrisLau Hi. Why are you invoking chooseDay and not resetting selected prop?

@Inbal-Tish I tried selected but it was not working for me and then i saw this on StackOverflow: https://stackoverflow.com/questions/52437947/agenda-dynamically-change-selected-day

I'm using the ExpandableCalendar and AgendaList. I'm able to get the date selected from the ExpandableCalendar using onDayPress but I cant seem to get the AgendaList to change the date. It seems to only change the date when it is an already rendered agenda list item (so an item that occurs close to the currently selected date) but will not change the AgendaList if I select a date that is a 10 items away. The latter will cause an onScrollToIndexFailed info: {"averageItemLength": 34.84615384615385, "highestMeasuredFrameIndex": 36, "index": 60} error to occur

KrisLau avatar Jun 08 '22 14:06 KrisLau

@KrisLau Yes, you can't scroll to an item that was not rendered, but the AgendaList's scroll is handled by the ExpandableCalendar (that's the whole point), you should not manage it yourself. If you need to change the date, change it in the CalendarProvider's date prop and the date should change in both the calendar and agenda list.

Inbal-Tish avatar Jun 09 '22 06:06 Inbal-Tish

@violabg You can check out our new docs site: https://wix.github.io/react-native-calendars/docs/Calendar#initialdate

Inbal-Tish avatar Jun 09 '22 06:06 Inbal-Tish

Modifying initialDate rather than onMonthChange results is some lag before the calendar is updated. I believe this is because it’s a useEffect call that we are triggering.

Is there another solution to modify the current month?

We cannot use onMonthChange because we are using a custom calendar header component which does not have the built in month change arrow at the two sides.

On Thu, 9 Jun 2022 at 07:12, Inbal Tish @.***> wrote:

initialDate

You can check out our new docs site: https://wix.github.io/react-native-calendars/docs/Calendar#initialdate

β€” Reply to this email directly, view it on GitHub https://github.com/wix/react-native-calendars/issues/1862#issuecomment-1150712507, or unsubscribe https://github.com/notifications/unsubscribe-auth/ASKGGRDUMCJBNI4KQZA4H73VOGDL5ANCNFSM5TB2VGHA . You are receiving this because you commented.Message ID: @.***>

--

Warmest Regards,

Chai Yi Hein

yiheinchai avatar Jun 09 '22 07:06 yiheinchai

Modifying initialDate rather than onMonthChange results is some lag before the calendar is updated. I believe this is because it’s a useEffect call that we are triggering. Is there another solution to modify the current month? We cannot use onMonthChange because we are using a custom calendar header component which does not have the built in month change arrow at the two sides.

What are you currently using with the ref? Can you add the snippet here?

Inbal-Tish avatar Jun 09 '22 07:06 Inbal-Tish

What are you currently using with the ref? Can you add the snippet here?

<Calendar
            initialDate={sharedDate.format('YYYY-MM-DD')}
            current={sharedDate.format('YYYY-MM-DD')}
            minDate={moment().format('YYYY-MM-DD')}
            hideExtraDays={true}
            enableSwipeMonths={true}

I am no longer using refs to modify the month. I am passing a prop into initialDate (ie. sharedDate). When ever the user changes the month of the calender via a custom parent component, I modify the prop to the child component, which updates initialDate.

However, this setup results in a lag when changing months.

yiheinchai avatar Jun 09 '22 07:06 yiheinchai

Perhaps we use forward refs and useImperativeHandler to expose methods of the calendar component?

yiheinchai avatar Jun 09 '22 07:06 yiheinchai

Perhaps we use forward refs and useImperativeHandler to expose methods of the calendar component?

I'm familiar with the forwardRef and useImperativeHandler solution, but I wish to avoid it (and so should you, as using ref is a risky move when you are not controlling the source code). I would like to solve the lag using the initialDate or to provide a proper tool for modifying the month. What did you use before initialDate to switch months?

Inbal-Tish avatar Jun 09 '22 08:06 Inbal-Tish

Perhaps we use forward refs and useImperativeHandler to expose methods of the calendar component?

I'm familiar with the forwardRef and useImperativeHandler solution, but I wish to avoid it (and so should you, as using ref is a risky move when you are not controlling the source code). I would like to solve the lag using the initialDate or to provide a proper tool for modifying the month. What did you use before initialDate to switch months?

I was accessing the addMonth method by using a ref on the Calendar component. This solution was suggested here.

yiheinchai avatar Jun 09 '22 08:06 yiheinchai

See my video below where I use, for example purpuses only, the onDayLongPress to switch months. I don't see leggines there, can you add a video to show me the issue with updating the initialDate prop?

https://user-images.githubusercontent.com/33805983/172803857-40228e5b-83f7-4f03-80bf-ae9a4ddd4492.mov

Inbal-Tish avatar Jun 09 '22 08:06 Inbal-Tish

Seems like the lag does not occur with a fresh RN project, might have to do with my own implementation.

yiheinchai avatar Jun 09 '22 09:06 yiheinchai

Hi there. I'm also having the same issue with the ref being non-existent after the latest upgrades. In my case, I have a complex set of components that make use of this library, and the only way to achieve some of the things in our project was to make use of refs to access the internal functions of the calendar components. Like @Inbal-Tish mentioned above, I agree that this is not ideal but in our case, we didn't see any other way to achieve what was intended. Furthermore, I recently also tried to make use of the initialDates prop, but it didn't really work as expected.

Also wanted to mention that I really appreciate all the effort put into this library and the people behind this, but it sounds like this is a breaking change, and IMHO should have been done in a major release, not a minor.

filipearena avatar Jun 17 '22 03:06 filipearena

@yiheinchai So you are changing the months with a custom component outside instead of the react-native-calendars arrows?

bruno-fialho avatar Jul 06 '22 21:07 bruno-fialho

That is correct.

On Thu, Jul 7, 2022 at 5:45 AM Bruno Fialho @.***> wrote:

@yiheinchai https://github.com/yiheinchai So you are changing the months with a custom component outside instead of the react-native-calendars arrows?

β€” Reply to this email directly, view it on GitHub https://github.com/wix/react-native-calendars/issues/1862#issuecomment-1176781509, or unsubscribe https://github.com/notifications/unsubscribe-auth/ASKGGRESH76NLLOXU3SWOT3VSX47PANCNFSM5TB2VGHA . You are receiving this because you were mentioned.Message ID: @.***>

yiheinchai avatar Jul 08 '22 08:07 yiheinchai

@KrisLau Yes, you can't scroll to an item that was not rendered, but the AgendaList's scroll is handled by the ExpandableCalendar (that's the whole point), you should not manage it yourself. If you need to change the date, change it in the CalendarProvider's date prop and the date should change in both the calendar and agenda list.

@Inbal-Tish Ok so i remember why I tried ref now. I just used the date prop and the date didn't change for the initial render and even when I call the setState in the onDayPress. Also pressing the today button doesn't seem to work eitehr? it only changes the date in the ExpandableCalendar but not in the AgendaList. In the picture I hardcode the date prop but i usually have selectedDay state there. Just did that to test

image

KrisLau avatar Aug 03 '22 17:08 KrisLau

@Inbal-Tish So the proposed solution to get the visible month was to use onVisibleMonthsChange (or possibly onMonthChange). The reason why I was using the ref for this is as follows.

First of all, I was able to remove almost all of my dependencies on the ref so that is the good news. The last one that I can`t figure out how to do is this one.

When trying to decide whether a row left or right is disabled, I need to know on which month am I on. I can get that value from onMonthChange of course but the issue is that when the calendar first gets mounted, onMonthChange is not called, it only gets called when the month changes for the first time.

A nice addition would be to somehow get a callback for onMonthChange when the calendar is mounted (or even better, some other callback function, something like onInitialRender(date)) or alternatively, disableArrowLeft and disableArrowRight can also provide the current month that I am on. I prefer the second scenario because, with that approach, I won`t even need to store the current date anywhere on my end.

disableArrowLeft should basically change its type to (date? XDate) => boolean | boolean instead of just being boolean.

Saikedo avatar Sep 03 '22 14:09 Saikedo

@Saikedo Hi. From what I understand you need to know the current month when the ExpandableCalendar mounts, right? What do you pass to the CalendarProvider date prop (a required prop)? The disableArrowLeft is not a function, it's a boolean passed to disable the arrow button and it is controlled by the user.

Inbal-Tish avatar Sep 19 '22 08:09 Inbal-Tish

@Inbal-Tish Yes, disableArrowLeft is not a function, the proposal was to make it into a bool | (currentDate) => boolean.

As for What do you pass to the CalendarProvider date prop (a required prop)?, I am using the Calendar component directly, so I dont pass anything to CalendarProvider and there is no such required prop in Calendar`.

Saikedo avatar Sep 21 '22 13:09 Saikedo

@Inbal-Tish Yes, disableArrowLeft is not a function, the proposal was to make it into a bool | (currentDate) => boolean.

As for What do you pass to the CalendarProvider date prop (a required prop)?, I am using the Calendar component directly, so I dont pass anything to CalendarProvider and there is no such required prop in Calendar`.

See if you're passing current or initialDate prop with the start date, if not the calendar will default to today's date, so you can set your initial const to that.

Inbal-Tish avatar Sep 22 '22 06:09 Inbal-Tish