You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Material UI StaticDatePicker自定义日期样式后点击选日失效求助

解决StaticDatePicker自定义renderDay后无法点击选中日期的问题

问题根源

  1. 参数顺序错误:你对renderDay的参数理解有误,MUI的renderDay并没有第四个dayComponent参数,第三个参数是包含isInCurrentMonth、disabled等属性的pickersDayProps对象。
  2. 丢失交互逻辑:你自定义的<div>完全替换了MUI默认的日期单元格组件,原组件内置的点击选中、状态判断等交互逻辑被丢弃,导致点击日期无法触发选择。

解决方案

复用MUI默认的日期单元格组件,通过React.cloneElement扩展它的样式属性,同时保留原有的交互逻辑;同时修正renderDay的参数顺序,正确使用传入的属性。

修改后的代码

import React from 'react'
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'
import { StaticDatePicker } from '@mui/x-date-pickers'
import { LocalizationProvider } from '@mui/x-date-pickers'
import { TextField } from '@mui/material'
import { makeStyles } from '@mui/styles'
import dayjs from 'dayjs'


const styles = makeStyles(() => ({
  pendingCloseDay: {
    backgroundColor: 'red',
    width: '35px', 
    height: '35px',
    padding: '1px',
  },
  closedDay: {
    backgroundColor: 'green',
    width: '35px', 
    height: '35px',
    padding: '1px',
  },
  noMovementsDay: {
    backgroundColor: 'white',
    width: '35px', 
    height: '35px',
    padding: '1px'
  },
  currentDay: {
    backgroundColor: 'blue',
    width: '35px', 
    height: '35px',
    padding: '1px'
  },
  futureDays: {
    backgroundColor: 'gray',
    width: '35px', 
    height: '35px',
    padding: '1px'
  },
  selectedDay: {
    backgroundColor: 'pink',
    width: '35px', 
    height: '35px',
    padding: '1px'
  }
}))

const Calendar = ({date, setDate, setShow}) => {
  const classes = styles()
  const today = dayjs() 
  
  const handleChange = (e) => {
    setDate(e)
    setShow(prev => !prev)
  }
  
  const mockDataForDays = (day, selectedDates, pickersDayProps) => {
    // 获取默认的日期单元格组件
    const defaultDayComponent = pickersDayProps.children
    let randomValueForDay = Math.random()
    const isSelected = day.isSame(selectedDates[0], 'day')
    const isToday = day.isSame(today, 'day')
    let className = ''

    const { isInCurrentMonth, disabled } = pickersDayProps

    if (isInCurrentMonth) {
      if (disabled) {
        className = isSelected ? classes.selectedDay : isToday ? classes.currentDay : classes.futureDays
      } else if (randomValueForDay >= 0.66) {
        className = isSelected ? classes.selectedDay : isToday ? classes.currentDay : classes.noMovementsDay
      } else if (randomValueForDay >= 0.33) {
        className = isSelected ? classes.selectedDay : isToday ? classes.currentDay : classes.closedDay
      } else {
        className = isSelected ? classes.selectedDay : isToday ? classes.currentDay : classes.pendingCloseDay
      }

      // 克隆默认组件,添加自定义样式类,保留原组件的所有交互属性
      return React.cloneElement(defaultDayComponent, {
        className: `${defaultDayComponent.props.className} ${className}`
      })
    }

    // 非当前月份的日期返回默认组件
    return defaultDayComponent
  }

  return (
    <LocalizationProvider dateAdapter={AdapterDayjs}>
      <StaticDatePicker
        sx={{'.MuiDayPicker-header': {gap: '0.5rem'}}}
        disableFuture={true}
        openTo='day'
        value={date}
        toolbarTitle=''
        onChange={handleChange}
        renderInput={params => <TextField {...params} />}
        componentsProps={{
          actionBar: {
            actions: []
          }
        }}
        renderDay={mockDataForDays}
      />
    </LocalizationProvider>
  )
}

export default Calendar

关键修改点

  1. 修正renderDay参数:使用正确的参数顺序(day, selectedDates, pickersDayProps),从pickersDayProps中获取isInCurrentMonth、disabled等属性。
  2. 复用默认组件:通过pickersDayProps.children获取MUI默认的日期单元格组件,用React.cloneElement为它添加自定义样式类,保留原有的点击选中逻辑。
  3. 优化日期判断:使用dayjs的isSame方法更准确地判断日期是否选中或为当天,避免原代码中可能的数组访问错误。

这样修改后,既能保留自定义的日期样式,又能恢复点击日期选中的功能。

内容的提问来源于stack exchange,提问作者Roberto

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 10:30:51