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

如何在TimePicker/DesktopDatePicker无效时禁用按钮?

解决MUI TimePicker/DesktopDatePicker无效输入时按钮仍可点击的问题

方案一:手动校验值并管理错误状态

直接通过监听Picker的onChange事件,每次值变化时校验是否为有效的Date对象,同时保留onError捕获组件抛出的错误,双向更新错误状态:

import { useState } from 'react';
import { Button, FormControl, FormHelperText, TextField } from '@mui/material';
import { TimePicker, DesktopDatePicker } from '@mui/x-date-pickers';
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';

export default function PickerForm() {
  const [dateValue, setDateValue] = useState(null);
  const [timeValue, setTimeValue] = useState(null);
  const [hasError, setHasError] = useState(false);

  // 统一校验日期和时间的有效性
  const checkValidity = () => {
    const isDateValid = dateValue instanceof Date && !isNaN(dateValue);
    const isTimeValid = timeValue instanceof Date && !isNaN(timeValue);
    setHasError(!(isDateValid && isTimeValid));
  };

  const handleDateChange = (newValue) => {
    setDateValue(newValue);
    checkValidity();
  };

  const handleTimeChange = (newValue) => {
    setTimeValue(newValue);
    checkValidity();
  };

  // 捕获组件抛出的错误,标记状态
  const handleError = () => {
    setHasError(true);
  };

  return (
    <LocalizationProvider dateAdapter={AdapterDateFns}>
      <FormControl error={hasError} sx={{ m: 2 }}>
        <DesktopDatePicker
          label="选择日期"
          value={dateValue}
          onChange={handleDateChange}
          onError={handleError}
          renderInput={(params) => <TextField {...params} />}
        />
        <TimePicker
          label="选择时间"
          value={timeValue}
          onChange={handleTimeChange}
          onError={handleError}
          renderInput={(params) => <TextField {...params} sx={{ mt: 2 }} />}
        />
        {hasError && <FormHelperText>日期或时间输入无效,请检查</FormHelperText>}
        <Button
          variant="contained"
          disabled={hasError}
          sx={{ mt: 2 }}
          onClick={() => console.log('执行保存逻辑')}
        >
          保存
        </Button>
      </FormControl>
    </LocalizationProvider>
  );
}

这个方法的核心是每次值变更时主动校验,不管用户是手动输入错误还是通过选择器修改,都能实时更新错误状态,解决了onError只触发错误出现、不触发错误消除的问题。

方案二:用react-hook-form自动管理表单校验

如果是复杂表单场景,推荐用react-hook-form集成,它会自动处理字段校验和状态更新,无需手动维护error变量:

import { useForm, Controller } from 'react-hook-form';
import { Button, TextField } from '@mui/material';
import { TimePicker, DesktopDatePicker } from '@mui/x-date-pickers';
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';

export default function PickerWithForm() {
  const { control, formState: { isValid }, handleSubmit } = useForm({
    mode: 'onChange', // 实时触发校验
    defaultValues: {
      date: null,
      time: null
    }
  });

  const onSubmit = (formData) => {
    console.log('保存数据:', formData);
    // 这里写你的保存逻辑
  };

  return (
    <LocalizationProvider dateAdapter={AdapterDateFns}>
      <form onSubmit={handleSubmit(onSubmit)} style={{ margin: 20 }}>
        <Controller
          name="date"
          control={control}
          rules={{ 
            required: '日期不能为空',
            validate: (val) => val instanceof Date && !isNaN(val) || '请输入有效的日期'
          }}
          render={({ field, fieldState: { error } }) => (
            <DesktopDatePicker
              label="选择日期"
              value={field.value}
              onChange={field.onChange}
              renderInput={(params) => (
                <TextField 
                  {...params} 
                  error={!!error} 
                  helperText={error?.message} 
                />
              )}
            />
          )}
        />
        <Controller
          name="time"
          control={control}
          rules={{ 
            required: '时间不能为空',
            validate: (val) => val instanceof Date && !isNaN(val) || '请输入有效的时间'
          }}
          render={({ field, fieldState: { error } }) => (
            <TimePicker
              label="选择时间"
              value={field.value}
              onChange={field.onChange}
              renderInput={(params) => (
                <TextField 
                  {...params} 
                  error={!!error} 
                  helperText={error?.message} 
                  sx={{ mt: 2 }} 
                />
              )}
            />
          )}
        />
        <Button
          variant="contained"
          type="submit"
          disabled={!isValid}
          sx={{ mt: 2 }}
        >
          保存
        </Button>
      </form>
    </LocalizationProvider>
  );
}

通过Controller把Picker注册到表单,设置校验规则后,isValid状态会自动根据所有字段的校验结果更新,按钮的disabled直接绑定!isValid,错误消除时按钮会自动恢复可用,完全不用手动处理状态重置。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 11:36:14