`shouldComponentUpdate` not getting called for my custom dayComponent

Description

I am trying to provide a custom component as my dayComponent and it is working. But inorder to improve the performance i want to implement shouldComponentUpdate on my Custom day component. Instead shouldComponentUpdate getting called every time componentDidMount is getting called, due to which i think my calendar is ver slow.

Please find my render function specifics below

I have state value which controls the markedDates based on conditions

let markedDates = {};

    if (this.state.showCustody) {
      markedDates = Object.assign({}, this.state.custodyDates);
    } else if (props.showEvents) {
      markedDates = Object.assign({},  this.state.eventsDates);
    }

Then i have DayItem as my custom day component.

<CalendarList
            {...props}
            horizontal
            pagingEnabled
            removeClippedSubviews={false}
            markingType={'multi-dot'}
            markedDates={markedDates}
            dayComponent={(params) => 
              (<DayItem
                params={params}
                props={props}
                .... //few more props
                />)
            }
          />

And my day component looks like this

class DayItem extends React.Component {

  componentDidMount(){
   console.log('componentDidMount')
  }

shouldComponentUpdate(nextProps, nextState) {
console.log('shouldComponentUpdate') 
return true
}

  render() {
    
    const {
      params,
      props,
      ... //few more props
    } = this.props;
    const selectedDays = this.props.selectedDays;
    const {date, marking, state} = params;

    
    return (
      <TouchableOpacity
        style={[
          styles.calendarDay,
          state === 'disabled' && !isSelected ? {opacity: 0.4} : {},
        ]}
        onPress={() => {
          !disablePress && !!onPress && onPress(date, state);
        }}>
        <View>
          <Text style={{textAlign: 'center', color: state === 'disabled' ? 'gray' : 'black'}}>
            {date.day}
          </Text>
        </View>
        <View style={styles.calendarDayMarks}>
          {dots.map((dot, i) => (
            <View
              key={i}
              style={[styles.calendarDayMark, {backgroundColor: dot}]}></View>
          ))}
        </View>
      </TouchableOpacity>
    );
  }
}

Expected Behavior

When there is a change in markedDates, shouldComponentUpdate of my day component will get called and i can check if there is a props change, if yes render the component if no do nothing. Currently my entire day component is getting recreated for no reason.

Observed Behavior

Everytime my parent component’s render gets called i can see componentDidMount getting printed in my console and shouldComponentUpdate never gets called. What am i missing here??

Environment

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

  • npm ls react-native-calendars:
my-family-plan@0.0.1 /Users/cdp/Pictures/MobileApp
└── react-native-calendars@1.294.0 

2 thoughts on “`shouldComponentUpdate` not getting called for my custom dayComponent

  1. mhhh i dont know if this will work.
    i tried some things the last time, never worked if we use arrow function as prop.

    So try this:

    export default React.memo(({ date, children, state, onPress, marking }) => {

    import MemoizedDay from "./MemoizedDay";

    dayComponent={MemoizedDay}

  2. This is not an issue with the library. This is an issue with your code and how React works in general.

    By inlining this code you create a new DayItem component every single time your Calendar component re-renders:

    dayComponent={(params) => 
                  (<DayItem
                    params={params}
                    props={props}
                    .... //few more props
                    />)
                }

    It creates a performance issue, because all days must be re-rendered even though no changes occurred. shouldComponentUpdate is never called, because component never updates – instead, a new component is created every single time.

    You should move this code to a function that always holds same reference.

    class MyScreen extends React.Component {
        renderDayItem(params) {
            return (
                    <DayItem
                        params={params}
                        props={this.props}
             />);
        }
    
        render() {
            return (
                <Calendar
                    ..........
                    dayComponent={this.renderDayItem}
                />
            );
        }
    }

    You could use PureComponent/React.memo to avoid using shouldComponentUpdate, but you still need to pass same reference to Calendar every single time. This is the main issue here.