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

Antd 5.6.3 RangePicker日期范围禁用功能异常求助

AntD 5.6.3 RangePicker 日期范围限制问题解决

问题描述

使用AntD 5.6.3版本的RangePicker组件,需求为:选中开始日期后,禁用该日期前后超过maxDays(默认3天)的日期范围,且选中时立即生效。但当前实现仅禁用了开始日期之前的日期,功能异常,且因依赖限制无法升级AntD版本。

用户原代码:

import { DatePicker } from 'antd';
import type { RangePickerProps } from 'antd/es/date-picker';
import { useState } from 'react';
import type { Dayjs } from 'dayjs';

interface Props {
  format?: string;
  maxDays?: number; // 최대 조회 기간 (일 단위)
  value?: [Dayjs | null, Dayjs | null] | null;
  onChange?: (dates: [Dayjs | null, Dayjs | null]) => void;
}

const { RangePicker } = DatePicker;

const Calendar = (props: Props) => {
  const [startDate, setStartDate] = useState<Dayjs | null>(null);
  const [selectedDates, setSelectedDates] = useState<[Dayjs | null, Dayjs | null] | null>(null);
  const [isSelectingStart, setIsSelectingStart] = useState<boolean>(true);
  const maxDays = props.maxDays || 3; // 기본 최대 조회 기간은 3일

  const disabledDate: RangePickerProps['disabledDate'] = (currentDate) => {
    if (isSelectingStart) {
      // 시작일을 선택 중일 때는 모든 날짜를 활성화
      return false;
    }

    if (!startDate) {
      // 시작일이 선택되지 않았을 때는 모든 날짜를 활성화
      return false;
    }
    // 시작일을 기준으로 -maxDays ~ +maxDays 범위 내의 날짜만 활성화
    const tooEarly = currentDate.isBefore(startDate.subtract(maxDays, 'days'), 'day');
    const tooLate = currentDate.isAfter(startDate.add(maxDays, 'days'), 'day');
    return tooEarly || tooLate;
  };

  const handleChange: RangePickerProps['onCalendarChange'] = (dates, dateStrings, info) => {
    if (dates && dates[0] && !dates[1]) {
      // 시작일이 선택되었을 때
      setStartDate(dates[0]);
    } else if (dates && dates[0] && dates[1]) {
      // 날짜 범위가 모두 선택되었을 때
      setStartDate(null); // 시작일 재선택을 위해 초기화
    }
    setSelectedDates(dates);
    setIsSelectingStart(info.range === 'start');

    if(props.onChange) {
      props.onChange(dates as [Dayjs | null, Dayjs | null]);
    }
  };


  return (
    <RangePicker
      format={props.format}
      disabledDate={disabledDate}
      onCalendarChange={handleChange}
      value={selectedDates}
    />
  );
};

export default Calendar;

解决方案

针对AntD 5.6.3版本的RangePicker特性,调整状态管理与disabledDate逻辑,解决内置规则覆盖自定义限制的问题:

修改后完整代码

import { DatePicker } from 'antd';
import type { RangePickerProps } from 'antd/es/date-picker';
import { useState, useEffect } from 'react';
import type { Dayjs } from 'dayjs';

interface Props {
  format?: string;
  maxDays?: number; // 최대 조회 기간 (일 단위)
  value?: [Dayjs | null, Dayjs | null] | null;
  onChange?: (dates: [Dayjs | null, Dayjs | null]) => void;
}

const { RangePicker } = DatePicker;

const Calendar = (props: Props) => {
  const [startDate, setStartDate] = useState<Dayjs | null>(null);
  const [endDate, setEndDate] = useState<Dayjs | null>(null);
  const [isSelectingStart, setIsSelectingStart] = useState<boolean>(true);
  const maxDays = props.maxDays || 3;

  // 同步外部传入的value到内部状态
  useEffect(() => {
    if (props.value) {
      setStartDate(props.value[0]);
      setEndDate(props.value[1]);
    } else {
      setStartDate(null);
      setEndDate(null);
    }
  }, [props.value]);

  const disabledDate: RangePickerProps['disabledDate'] = (current) => {
    if (!current) return true;

    if (isSelectingStart) {
      // 选择开始日期时:若已有结束日期,限制在结束日期往前maxDays范围内
      if (endDate) {
        return current.isAfter(endDate, 'day') || current.isBefore(endDate.subtract(maxDays, 'days'), 'day');
      }
      return false;
    } else {
      // 选择结束日期时:严格限制在开始日期的±maxDays范围内
      if (!startDate) return false;
      const minDate = startDate.subtract(maxDays, 'days');
      const maxDate = startDate.add(maxDays, 'days');
      return current.isBefore(minDate, 'day') || current.isAfter(maxDate, 'day');
    }
  };

  const handleCalendarChange: RangePickerProps['onCalendarChange'] = (dates, _, info) => {
    setIsSelectingStart(info.range === 'start');
    if (dates?.[0]) setStartDate(dates[0]);
    if (dates?.[1]) setEndDate(dates[1]);
  };

  const handleChange: RangePickerProps['onChange'] = (dates) => {
    props.onChange?.(dates as [Dayjs | null, Dayjs | null]);
  };

  // 兼容受控/非受控模式
  const selectedDates = props.value ?? [startDate, endDate];

  return (
    <RangePicker
      format={props.format}
      disabledDate={disabledDate}
      onCalendarChange={handleCalendarChange}
      onChange={handleChange}
      value={selectedDates}
    />
  );
};

export default Calendar;

关键修改说明

  1. 拆分状态管理:将selectedDates拆分为startDate和endDate,精准控制选中日期的生命周期,避免选中完整范围后清空开始日期的错误逻辑。
  2. 区分面板禁用规则:明确开始/结束日期面板的不同限制逻辑,规避AntD 5.6.3内置的日期优先级规则对自定义限制的覆盖。
  3. 同步外部value:通过useEffect同步外部传入的value,确保受控组件的状态一致性。
  4. 分离事件处理:将临时选择的状态更新放在onCalendarChange中,最终确认的选择放在onChange中,符合组件的事件触发逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 01:24:50