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

基于React-Datepicker实现用户专属配送日期展示与禁用功能求助

解决方案:动态展示用户专属配送日并过滤React-Datepicker选项

我会分三个核心部分帮你落地需求:提取用户专属配送配置、计算下一个可用配送日、配置React-Datepicker的日期过滤规则。

1. 从Auth0用户元数据中提取配送日

首先要从Auth0返回的用户对象里拿到对应区域的配送日。假设你的user.user_metadata里存的是类似deliveryDay: "Monday"(星期名称)或者deliveryDay: 1(MomentJS的星期数字,1=周一,0=周日),先统一转换成MomentJS能直接用的星期数字:

import moment from 'moment';
import { useAuth0 } from '@auth0/auth0-react';

// 获取Auth0用户对象
const { user } = useAuth0();

// 转换配送日为Moment兼容的星期数字(0=周日,1=周一...6=周六)
const getUserDeliveryDay = () => {
  const deliveryDay = user?.user_metadata?.deliveryDay;
  if (!deliveryDay) return null;

  // 处理字符串格式的星期名称(比如"Monday")
  if (typeof deliveryDay === 'string') {
    return moment().day(deliveryDay).day();
  }
  // 已经是数字则直接返回
  return Number(deliveryDay);
};

const userDeliveryDay = getUserDeliveryDay();

2. 计算下一个可用配送日

接下来要结合当前时间和用户配送日,算出符合规则的下一个配送日——这里要注意当天是否过了配送截止时间(比如公司规定当天12点前下单才能走当天配送,否则要等下一个周期):

// 可根据业务调整配送截止时间
const DELIVERY_CUTOFF_HOUR = 12;

const getNextDeliveryDate = () => {
  if (!userDeliveryDay) return null;

  const today = moment();
  const todayDay = today.day();
  const isTodayDeliveryDay = todayDay === userDeliveryDay;
  const isAfterCutoff = today.hour() >= DELIVERY_CUTOFF_HOUR;

  let nextDelivery = today.clone().day(userDeliveryDay);
  // 如果今天是配送日但已过截止时间,或者计算出的日期在今天之前,就往后推一周
  if ((isTodayDeliveryDay && isAfterCutoff) || nextDelivery.isBefore(today, 'day')) {
    nextDelivery.add(7, 'days');
  }

  return nextDelivery; // 返回moment对象,方便后续格式化展示
};

const nextDeliveryDate = getNextDeliveryDate();

然后你就可以把这个日期展示给用户:

{nextDeliveryDate && (
  <p>您的下一个配送日:{nextDeliveryDate.format('YYYY年MM月DD日 dddd')}</p>
)}

3. 配置React-Datepicker过滤可选日期

React-Datepicker的filterDate属性可以自定义哪些日期可选。我们写一个过滤函数,只允许用户的配送日且是**今天及以后(符合截止时间规则)**的日期:

import DatePicker from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css';
import { useState } from 'react';

const [selectedDate, setSelectedDate] = useState(null);

// 日期过滤函数
const filterAllowedDates = (date) => {
  if (!userDeliveryDay) return false;

  const dateMoment = moment(date);
  const today = moment();

  // 不是用户配送日直接禁用
  if (dateMoment.day() !== userDeliveryDay) return false;
  // 今天之前的日期直接禁用
  if (dateMoment.isBefore(today, 'day')) return false;
  // 如果是今天,判断是否过了截止时间
  if (dateMoment.isSame(today, 'day')) {
    return today.hour() < DELIVERY_CUTOFF_HOUR;
  }

  // 符合条件的未来配送日允许选择
  return true;
};

// 在组件中使用DatePicker
<DatePicker
  selected={selectedDate}
  onChange={(date) => setSelectedDate(date)}
  filterDate={filterAllowedDates}
  dateFormat="yyyy-MM-dd EEEE"
  placeholderText="选择配送日期"
/>

优化建议:封装成自定义Hook

把这些逻辑封装成自定义Hook,方便在多个组件中复用,代码也更整洁:

import { useAuth0 } from '@auth0/auth0-react';
import moment from 'moment';

export const useUserDelivery = () => {
  const { user } = useAuth0();
  const DELIVERY_CUTOFF_HOUR = 12;

  // 获取用户配送日数字
  const userDeliveryDay = (() => {
    const deliveryDay = user?.user_metadata?.deliveryDay;
    if (!deliveryDay) return null;
    if (typeof deliveryDay === 'string') {
      return moment().day(deliveryDay).day();
    }
    return Number(deliveryDay);
  })();

  // 计算下一个配送日
  const getNextDeliveryDate = () => {
    if (!userDeliveryDay) return null;
    const today = moment();
    const todayDay = today.day();
    const isTodayDeliveryDay = todayDay === userDeliveryDay;
    const isAfterCutoff = today.hour() >= DELIVERY_CUTOFF_HOUR;

    let nextDelivery = today.clone().day(userDeliveryDay);
    if ((isTodayDeliveryDay && isAfterCutoff) || nextDelivery.isBefore(today, 'day')) {
      nextDelivery.add(7, 'days');
    }
    return nextDelivery;
  };

  // 日期过滤函数
  const filterAllowedDates = (date) => {
    if (!userDeliveryDay) return false;
    const dateMoment = moment(date);
    const today = moment();

    if (dateMoment.day() !== userDeliveryDay) return false;
    if (dateMoment.isBefore(today, 'day')) return false;
    if (dateMoment.isSame(today, 'day')) {
      return today.hour() < DELIVERY_CUTOFF_HOUR;
    }
    return true;
  };

  return {
    userDeliveryDay,
    nextDeliveryDate: getNextDeliveryDate(),
    filterAllowedDates
  };
};

在组件里直接调用这个Hook即可:

const { nextDeliveryDate, filterAllowedDates } = useUserDelivery();

// 展示下一个配送日
{nextDeliveryDate && (
  <div>
    <h3>您的下一个配送日:</h3>
    <p>{nextDeliveryDate.format('YYYY年MM月DD日 dddd')}</p>
  </div>
)}

// 使用DatePicker
<DatePicker
  selected={selectedDate}
  onChange={setSelectedDate}
  filterDate={filterAllowedDates}
  dateFormat="yyyy-MM-dd EEEE"
/>

注意事项

  • 确认MomentJS的星期数字和你存储的配送日对应正确(比如moment().day(1)对应周一,moment().day(0)对应周日)。
  • 如果Auth0的user_metadata里存的是其他格式(比如中文“周一”),需要调整转换逻辑适配。
  • 配送截止时间可以改成动态配置,比如从后端接口获取。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 18:57:41