-
I wanted to style it with div using grid style instead of using table, so I made everything like month, week, etc., with div. However, when I just insert the component, countless re-renders occur. Even wrapping the props with useMemo and the custom component with React.memo doesn't improve the situation at all. If I exclude the component, there are no re-renders, so could the created component be the problem? I need help. used library: emotion/styled, classNames const mockProducts = [{
id: 1,
name: "product1",
image_url: "https://placehold.co/400",
start_at: "2025-01-06T05:13:38.537Z",
end_at: "2025-01-11T05:13:38.537Z",
},
{
id: 2,
name: "product2",
image_url: "https://placehold.co/400",
start_at: "2025-01-13T05:13:38.537Z",
end_at: "2025-01-15T05:13:38.537Z",
},
{
id: 3,
name: "product3",
image_url: "https://placehold.co/400",
start_at: "2025-01-15T05:13:38.537Z",
end_at: "2025-01-20T05:13:38.537Z",
},
{
id: 4,
name: "product4",
image_url: "https://placehold.co/400",
start_at: "2025-01-27T05:13:38.537Z",
end_at: "2025-01-30T05:13:38.537Z",
}]
export const GroupPurchaseCalendar = () => {
const products = mockProducts
const getProductImage = (date: Date) => {
return (
products?.find((purchaseInfo) =>
isSameDay(date, toZonedTime(purchaseInfo.start_at, 'UTC')),
)?.image_url || ''
)
}
return (
<CalendarContainer>
<DayPicker
mode="range"
disabled
showOutsideDays
modifiers={{
selected: products
.map((date) => toZonedTime(date.start_at, 'UTC'))
.concat(products.map((date) => toZonedTime(date.end_at, 'UTC'))),
range_start: products.map((date) =>
toZonedTime(date.start_at, 'UTC'),
),
range_end: products.map((date) => toZonedTime(date.end_at, 'UTC')),
range_middle: (date: Date) => {
const isBetween = products.some((originData) => {
return (
isAfter(date, originData.start_at) &&
isBefore(date, originData.end_at)
)
})
return isBetween || false
},
}}
hideNavigation
startMonth={subMonths(new Date(), 1)}
endMonth={addMonths(new Date(), 1)}
weekStartsOn={1}
locale={ko}
components={{
MonthGrid: (props) => <CustomMonthGrid {...props} />,
MonthCaption: (props) => <CalendarCustomMonthCaption {...props} />,
Weekdays: (props) => <CustomWeekdays {...props} />,
Weekday: (props) => <CustomWeekday {...props} />,
Weeks: (props) => <CustomWeeks {...props} />,
Week: (props) => <CustomWeek {...props} />,
Day: ({ day, modifiers, ...props }) => (
<CalendarCustomDay
day={day}
modifiers={modifiers}
{...props}
imgSrc={getProductImage(day.date)}
/>
),
}}
/>
</CalendarContainer>
)
}
const CalendarContainer = styled.div`
padding: 12px;
border-radius: 8px;
background-color: #FFFFFF;
`
const CustomMonthGrid = styled.div`
display: flex;
flex-direction: column;
gap: 4px;
`
const CustomWeekdays = styled.div`
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
justify-content: center;
text-align: center;
`
const CustomWeekday = styled.div`
font-size: 10px;
font-style: normal;
font-weight: 700;
line-height: 100%;
color: #CACACE;
`
const CustomWeeks = styled.div`
display: flex;
flex-direction: column;
gap: 4px;
`
const CustomWeek = styled.div`
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
justify-content: center;
`
interface CalendarCustomDayProps extends DayProps {
imgSrc?: string
}
const CalendarCustomDay = ({
day,
modifiers,
className,
imgSrc,
}: CalendarCustomDayProps) => {
const { outside, range_end, range_start, range_middle, selected } = modifiers
return (
<StyledDay
isOutside={outside}
className={classNames(className, {
range_start: range_start,
range_end: range_end,
range_middle: range_middle,
selected: selected,
})}
backgroundImgSrc={imgSrc}
>
<div className="day">{day.date.getDate()}</div>
</StyledDay>
)
}
const StyledDay = styled.div<{
isOutside: boolean
backgroundImgSrc?: string
}>`
padding: 0 2px;
color: ${({ theme, isOutside }) =>
isOutside ? #CACAE : #121212};
opacity: 1;
& .day {
aspect-ratio: 1;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
min-width: 44px;
min-height: 44px;
}
&.range_start,
&.range_middle {
background-color: #F9F9F9;
}
&.range_end .day {
background-color: #CACAE;
border-radius: 100%;
}
&.range_start .day {
border-radius: 100%;
background-image: ${({ backgroundImgSrc }) =>
`url(${backgroundImgSrc})` || 'none'};
background-color: #18181B66;
background-blend-mode: darken;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
color: #FFFFFF;
}
&.range_start {
border-top-left-radius: 100%;
border-bottom-left-radius: 100%;
}
&.range_end {
border-top-right-radius: 100%;
border-bottom-right-radius: 100%;
}
&.range_start.range_middle.range_end {
border-radius: 0;
}
` |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 1 reply
-
Hi @SoheeP
You'll have to change the way you pass the I'll open a PR to fix the docs. |
Beta Was this translation helpful? Give feedback.
-
@gpbl |
Beta Was this translation helpful? Give feedback.
Hi @SoheeP
I just noticed that the documentation for Custom Components is misleading, you are passing the custom components exactly as the documentation specifies, but you should pass the functional components directly, as follow:
You'll have to change the way you pass the
imgSrc
prop to theCalendarCustomDay
, as you cannot inline the render function for it as currently stated in the docs.One potential solu…