Agenda : "shouldComponentUpdate" is not working properly
See original GitHub issueDescription
Hi, When the name of an item for a day has changed (other than the first), the reservation component does not trigger the update.
Expected Behavior
Trigger update for all changed items.
Suggested fix
I think the issue came from : reservation We see that we say do NOT update the reservation if the d1/d2 does not exist. And we know that d1/d2 is a date that only exists for the first reservation item. That’s why I think only my first item is updated.
shouldComponentUpdate(nextProps: ReservationProps) {
const d1 = this.props.date;
const d2 = nextProps.date;
const r1 = this.props.item;
const r2 = nextProps.item;
let changed = true;
if (!d1 && !d2) {
changed = false; // HERE
} else if (d1 && d2) {
if (d1.getTime() !== d2.getTime()) {
changed = true;
} else if (!r1 && !r2) {
changed = false;
} else if (r1 && r2) {
if ((!d1 && !d2) || (d1 && d2)) {
if (isFunction(this.props.rowHasChanged)) {
changed = this.props.rowHasChanged(r1, r2);
}
}
}
}
return changed;
}
Environment
npm ls react-native-calendars
: react-native-calendars@1.1280.0npm ls react-native
: react-native@0.66.4
Device/emulator/simulator & OS version: Android / Galaxy A12 / Android version : 11
Reproducible Demo
I took the example of the demo by adding an action which should modify the name of the clicked item by “Has changed !” Below the code :
import React, {Component} from 'react';
import {StyleSheet, Text, TouchableOpacity, View} from 'react-native';
import {Agenda, AgendaEntry, AgendaSchedule, DateData} from 'react-native-calendars';
interface State {
items?: AgendaSchedule;
}
export default class AgendaScreen extends Component<State> {
state: State = {
items: undefined,
};
render() {
return (
<Agenda
reservationsKeyExtractor={item => `${item.reservation?.day}`}
items={this.state.items}
loadItemsForMonth={this.loadItems}
selected={'2017-05-16'}
renderItem={this.renderItem}
renderEmptyDate={this.renderEmptyDate}
rowHasChanged={this.rowHasChanged}
showClosingKnob={true}
// markingType={'period'}
// markedDates={{
// '2017-05-08': {textColor: '#43515c'},
// '2017-05-09': {textColor: '#43515c'},
// '2017-05-14': {startingDay: true, endingDay: true, color: 'blue'},
// '2017-05-21': {startingDay: true, color: 'blue'},
// '2017-05-22': {endingDay: true, color: 'gray'},
// '2017-05-24': {startingDay: true, color: 'gray'},
// '2017-05-25': {color: 'gray'},
// '2017-05-26': {endingDay: true, color: 'gray'}}}
// monthFormat={'yyyy'}
// theme={{calendarBackground: 'red', agendaKnobColor: 'green'}}
//renderDay={(day, item) => (<Text>{day ? day.day: 'item'}</Text>)}
// hideExtraDays={false}
// showOnlySelectedDayItems
/>
);
}
loadItems = (day: DateData) => {
const items = this.state.items || {};
setTimeout(() => {
for (let i = -15; i < 85; i++) {
const time = day.timestamp + i * 24 * 60 * 60 * 1000;
const strTime = this.timeToString(time);
if (!items[strTime]) {
items[strTime] = [];
const numItems = 3;
for (let j = 0; j < numItems; j++) {
items[strTime].push({
name: 'Item for ' + '#' + j,
height: Math.max(50, Math.floor(Math.random() * 150)),
day: strTime + j,
});
}
}
}
const newItems: AgendaSchedule = {};
Object.keys(items).forEach(key => {
newItems[key] = items[key];
});
this.setState({
items: newItems,
});
}, 1000);
};
updateItem = (id: string) => {
const newItems: AgendaSchedule = {...this.state.items};
if (this.state.items) {
Object.keys(this.state.items).forEach(key => {
newItems[key] = this.updateAgendaEntry(key, id);
});
this.setState({
items: newItems,
});
}
};
updateAgendaEntry = (date: string, id: string) => {
let agendaEntryToUpdate: AgendaEntry[] = Object.assign([], this.state.items?.[date]);
let index = agendaEntryToUpdate.findIndex(a => a.day === id);
agendaEntryToUpdate[index] = Object.assign(
{},
{
...agendaEntryToUpdate[index],
name: 'Has changed !',
}
);
return agendaEntryToUpdate;
};
renderItem = (reservation: AgendaEntry, isFirst: boolean) => {
const fontSize = isFirst ? 16 : 14;
const color = isFirst ? 'black' : '#43515c';
return (
<TouchableOpacity style={[styles.item, {height: reservation.height}]} onPress={() => this.updateItem(reservation.day)}>
<Text style={{fontSize, color}}>{reservation.name}</Text>
</TouchableOpacity>
);
};
renderEmptyDate = () => {
return (
<View style={styles.emptyDate}>
<Text>This is empty date!</Text>
</View>
);
};
rowHasChanged = (r1: AgendaEntry, r2: AgendaEntry) => {
return r1.name !== r2.name;
};
timeToString(time: number) {
const date = new Date(time);
return date.toISOString().split('T')[0];
}
}
const styles = StyleSheet.create({
item: {
backgroundColor: 'white',
flex: 1,
borderRadius: 5,
padding: 10,
marginRight: 10,
marginTop: 17,
},
emptyDate: {
height: 15,
flex: 1,
paddingTop: 30,
},
});
Issue Analytics
- State:
- Created a year ago
- Reactions:5
- Comments:10
Top Results From Across the Web
shouldComponentUpdate not working in child component ...
shouldComponentUpdate () affect on parent component. If it returns true, parent component will be rerender. So, I think you should move ...
Read more >Should I use shouldComponentUpdate? - James K Nelson
Maintaining shouldComponentUpdate is hard The thing is, shouldComponentUpdate is sometimes necessary, and certainly makes your app respond ...
Read more >Memoization in React js - Topcoder
... challenging problems, and tap into specialized skills on demand. ... It depends on the shouldComponentUpdate() lifecycle method but it ...
Read more >How To Use Inline Functions In React Applications Efficiently
Inline function definitions are right where they are invoked or passed down. ... The comparison checks in shouldComponentUpdate and tells React to re-render ......
Read more >I wish I knew these before diving into React | by Canberk Morelli
Setting shouldComponentUpdate wrongly or forgetting that you set it can cause major problems since your component may not be updated as ...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
I seem to have a similar problem here.
Agenda
does not rerender whenitems
changes.Any updates on the issue? Patched the library for now, but it would be nice to see this fixed.