ReactJS日期输入框:如何根据月份动态限制日期最大值?
问题分析与修复方案
你的代码存在几个关键问题,导致动态日期限制功能未生效,以下是具体问题和修复步骤:
1. maxDayInMonth 函数逻辑错误
- 第一个条件分支错误使用了未定义的
setMaxDay = 28,应改为return 28; - 闰年判断不严谨,未考虑整百年需被400整除才是闰年的规则(比如1900年不是闰年,2000年是);
- 输入的月份/年份是字符串类型,直接和数字比较会出现类型不匹配(比如
"2" === 2结果为false)。
修正后的函数:
const maxDayInMonth = (monthStr, yearStr) => { const month = Number(monthStr); const year = Number(yearStr); // 未输入月份/年份时返回默认最大值,避免报错 if (!month || !year) return 31; // 标准闰年判断逻辑 const isLeapYear = (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; if (month === 2) { return isLeapYear ? 29 : 28; } else if ([4, 6, 9, 11].includes(month)) { return 30; } else { return 31; } };
2. 未正确管理表单状态
你提到了 useState 但代码中没有定义和更新 formData 的状态,导致月份/年份变化时,组件不会重新计算日期输入框的 max 属性。
添加状态定义并修正 handleChange:
const [formData, setFormData] = useState({ dob_day: '', dob_month: '', dob_year: '' }); const handleChange = (e) => { const value = e.target.type === "checkbox" ? e.target.checked : e.target.value; const name = e.target.name; // 更新表单状态,触发组件重新渲染 setFormData(prev => ({ ...prev, [name]: value })); // 当月份/年份变化时,手动触发日期输入框的HTML5校验 if (name === 'dob_month' || name === 'dob_year') { const dayInput = document.getElementById('dob_day'); dayInput?.checkValidity(); } };
3. 确保HTML5校验生效
HTML5默认只会在表单提交或输入框失去焦点时校验,当 max 值动态变化后,需要手动调用 checkValidity() 触发校验,上面的 handleChange 中已经添加了这部分逻辑。
完整修复后的代码
import { useState } from "react"; import { useCookies } from 'react-cookie'; import { useNavigate } from "react-router-dom"; import axios from "axios"; const YourComponent = () => { const [formData, setFormData] = useState({ dob_day: '', dob_month: '', dob_year: '' }); const [cookies, setCookie] = useCookies(); const navigate = useNavigate(); const handleChange = (e) => { const value = e.target.type === "checkbox" ? e.target.checked : e.target.value; const name = e.target.name; setFormData(prev => ({ ...prev, [name]: value })); // 触发日期输入框校验 if (name === 'dob_month' || name === 'dob_year') { const dayInput = document.getElementById('dob_day'); dayInput?.checkValidity(); } }; const maxDayInMonth = (monthStr, yearStr) => { const month = Number(monthStr); const year = Number(yearStr); if (!month || !year) return 31; const isLeapYear = (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; if (month === 2) { return isLeapYear ? 29 : 28; } else if ([4, 6, 9, 11].includes(month)) { return 30; } else { return 31; } }; const minYear = new Date().getFullYear() - 100; const maxYear = new Date().getFullYear() - 18; return ( <> <input id="dob_day" type="number" name="dob_day" placeholder="DD" min="1" max={maxDayInMonth(formData.dob_month, formData.dob_year)} required={true} value={formData.dob_day} onChange={handleChange} /> <input id="dob_month" type="number" name="dob_month" placeholder="MM" min="1" max="12" required={true} value={formData.dob_month} onChange={handleChange} /> <input id="dob_year" type="number" name="dob_year" placeholder="YYYY" min={minYear} max={maxYear} required={true} value={formData.dob_year} onChange={handleChange} /> </> ); }; export default YourComponent;
内容的提问来源于stack exchange,提问作者AdaCra
相关产品推荐
相关产品推荐

