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

`Agenda` list Items incorrectly rendering on update

Open JacobJaffe opened this issue 3 years ago • 14 comments

Hello -- I think I found a bug in the AgendaList due to the current key extraction.

When I navigate back in the agenda, e.g. from a Monday to Sunday, and if both of those days have arrays of events, the FlatList isn't rendering the correct item. Instead, an item previously rendered gets used. I'm pretty sure this is because of the string coercion of the indices used in the current key extraction:

https://github.com/wix/react-native-calendars/blob/74bc7fe05ed3883d3d8cbd56e3cd5a565543c385/src/agenda/reservation-list/index.tsx#L261:

  keyExtractor = (_item: DayAgenda, index: number) => String(index);

this seems to me like a pretty good example of the index-key anti pattern described here: https://robinpokorny.medium.com/index-as-a-key-is-an-anti-pattern-e0349aece318

This seems straightforward to fix, by at least exposing a keyExtractor prop to the AgendaList.

I'll put together a minimal reproduction of this when I get the time.

JacobJaffe avatar Feb 15 '22 03:02 JacobJaffe

Easiest way to reproduce is to load the agenda example and add showOnlySelectedDayItems={true} simulator_screenshot_5889124F-7497-4F95-A40D-075BA774E0B9

simulator_screenshot_EA40B60B-A98F-4FF0-924D-B0FEFE694DE0

eladgel avatar Feb 15 '22 07:02 eladgel

@Inbal-Tish

eladgel avatar Feb 15 '22 07:02 eladgel

@JacobJaffe I've added this pr in the meantime: https://github.com/wix/react-native-calendars/pull/1792

eladgel avatar Feb 15 '22 11:02 eladgel

Hi @eladgel ! Thank you for the reproduction. I've opened a new PR that addresses this + other issues with the Agenda not accepting generic items at: #1794.

JacobJaffe avatar Feb 15 '22 19:02 JacobJaffe

@eladgel @JacobJaffe Hi guys. Thank you for opening the issue and PRs - much appreciated! I added a fix to move things faster. You can follow this #1795

Inbal-Tish avatar Feb 16 '22 07:02 Inbal-Tish

^Hi there I have found a potential solution to this issue: can check #1890

DonovanVA avatar May 30 '22 11:05 DonovanVA

Dear Zeen, Regarding your issue above, check .../agenda/reservation-list/index.js, in that file, search for the line of code where ... } else { for (let i = 0; i < 31; i++) { const res = this.getReservationsForDay(iterator, props);

if (res) { reservations = reservations.concat(res); } iterator.addDays(1); } } change it to } else { const res = this.getReservationsForDay(iterator, props); if (res) { reservations = res; } iterator.addDays(1); }

This will render the reservations not in a list of 31 days, but just the item itself on that day. Hope this helps! Sincerely, Donovan Ng

On Fri, 3 Jun 2022 at 17:31, zeentan22 @.***> wrote:

Hi, may I ask how u managed to only show the items for that particular day that was pressed. Currently, items from other days appear in my app which is not what I desire. I would appreciate greatly if you are able to help me. Thanks!

— Reply to this email directly, view it on GitHub https://github.com/wix/react-native-calendars/issues/1791#issuecomment-1145779668, or unsubscribe https://github.com/notifications/unsubscribe-auth/AURSUDFN2GTM7KOYFS7MGN3VNHGGBANCNFSM5ONJ332A . You are receiving this because you commented.Message ID: @.***>

DonovanVA avatar Jun 03 '22 10:06 DonovanVA

I am still facing the same issue, anyone could find a walk around to it

minaairsupport avatar Aug 09 '22 14:08 minaairsupport

Hi minaairsupport,

DonovanVA solution is correct and helps me solve the issue.

Just change the last code snippet to this and it should work.

if (sameDate(newSelectedDate, prevState.selectedDay)) { this.setState({ reservations: [] }, () => this.updateReservations(this.props)); }

zeentan22 avatar Aug 09 '22 23:08 zeentan22

Thanks, @zeentan22 I wish they could release this fix instead of making a walk around @Inbal-Tish if you don't mind could you merge this fix so we could have it in next release

minaairsupport avatar Aug 11 '22 17:08 minaairsupport

I think I figure it out we need to override reservationsKeyExtractor to get the right id from the data

 <Agenda
        items={selectedDates}
        renderItem={renderItem}
        showOnlySelectedDayItems={true}
  reservationsKeyExtractor={(item) => {
          console.log('item', item);
          return item?.reservation?.id; ---> replace with proper id name 
        }}
        
        />

minaairsupport avatar Aug 11 '22 17:08 minaairsupport

@minaairsupport Hi. I'm not sure I understand what fix we are talking about. If you need a custom keyExtractor pass it to the reservationsKeyExtractor prop. This will return the item and the index as a parameter, much like the keyExtractor prop:

reservationsKeyExtractor={(item, index) => {
          return `${item?.reservation?.day}${index}`;
        }}

Inbal-Tish avatar Aug 14 '22 05:08 Inbal-Tish

Hi @Inbal-Tish expose reservationsKeyExtractor is a walk-around to fixing the incorrect view for the list. I wish this fixed by the library itself by doing the right checks.

like this one

if (sameDate(newSelectedDate, prevState.selectedDay)) { this.setState({ reservations: [] }, () => this.updateReservations(this.props)); }

minaairsupport avatar Aug 17 '22 17:08 minaairsupport

@minaairsupport Hi. Care to submit a PR on this?

Inbal-Tish avatar Aug 18 '22 06:08 Inbal-Tish

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Nov 19 '22 15:11 stale[bot]

Guys i have this issue but im using agenda instead of flat list, how can i fix it?

Delocy avatar Jun 11 '23 12:06 Delocy

I think I figure it out we need to override reservationsKeyExtractor to get the right id from the data

 <Agenda
        items={selectedDates}
        renderItem={renderItem}
        showOnlySelectedDayItems={true}
  reservationsKeyExtractor={(item) => {
          console.log('item', item);
          return item?.reservation?.id; ---> replace with proper id name 
        }}
        
        />

This worked for me!

kyle-helping-hand avatar Dec 14 '23 23:12 kyle-helping-hand

if (sameDate(newSelectedDate, prevState.selectedDay)) { this.setState({ reservations: [] }, () => this.updateReservations(this.props)); }

Please where i add above lines of code?

gkasireddy202 avatar Jan 31 '24 17:01 gkasireddy202