javascriptreactjsantdant-design-pro

antd Calendar duplicates the dates if I use cellRender in React.js


I was trying to reuse the antd calendar component for few months and highlight some specific days on each Calendar ( in light green). To perform this feature, I used cellRender to customize the calendar.

But when I do it, it duplicates the dates on each calendar as below screenshot. And also the dates are not selectable. The other thing is it always keep selected the current date (in dark green) by default. My question is,

  1. How can I keep the default selected date unselected.
  2. How avoid this date duplication?
  3. And still keep the dates selectable as I need ?

calendar_issue_image

These are the utilized package versions:

React version:     "react": "^18.2.0",

antd version:     "antd": "^5.4.6",

The code snippet:

CalendarList.jsx

import React from 'react'
import CalendarCard from './card/CalendarCard'
import dayjs from 'dayjs';
import './CalenderList.css';

let currentMonth = dayjs().month();
const monthsCount = 12;
const days = ['Wednesday', 'Thursday'];

const CalendarList= () => {
  return (
    <div className='CalendarList'>
      {Array.from({ length: monthsCount }, (_, i) => (
        <CalendarCard key={i} month={dayjs().month(currentMonth + i)}  days={days}/>
      ))}
    </div>
  )
}

export default CalendarList

CalendarCard.jsx

import React from 'react';
import { Calendar, theme } from 'antd';
import './CalendarCard.css';

const CalendarCard = ({ month, days }) => {
    const { token } = theme.useToken();

    const dateCellRender = (value) => {
        if (value.month() === month.month()) {
            const dayOfWeek = value.format('dddd');
            if (days.includes(dayOfWeek)) {
                return <div className='highlighted-day'>{value.date()}</div>
            }
        }
        return <div>{value.date()}</div>
    };

    const headerRender = ({ value }) => {
        return (
            <div style={{ padding: '10px', textAlign: 'center', fontSize: '16px', fontWeight: 'bold' }}>
                {value.format('MMMM YYYY')}
            </div>
        );
    }

    const onDateSelect = (value) => {
        console.log(value)
    }

    const wrapperStyle = {
        width: 300,
        border: `1px solid ${token.colorBorderSecondary}`,
        borderRadius: token.borderRadiusLG,
    };

    return (
        <div style={wrapperStyle}>
            <Calendar
                fullscreen={false}
                headerRender={headerRender}
                value={month}
                mode='month'
                onSelect={onDateSelect}
                cellRender={dateCellRender}
            />
        </div>
    )
}

export default CalendarCard

CalendarCard.css

.highlighted-day  {
    background-color: #87d068;
    color: white;
    border-radius: 4px;
}

click to open codesandbox


Solution

  • The docs define 2 cellRenderer methods: dateCellRender and dateFullCellRender. The first one appends your content below the default content of the cell, while the second displays only the value returned by the callback. Change the prop name from dateCellRender to dateFullCellRender. That should remove the default content.