react-date-picker组件tileDisabled属性失效问题排查及替代组件推荐求助
react-date-picker组件tileDisabled属性失效问题排查及替代组件推荐求助
我在做一个项目的预订模块,用的是react-date-picker组件,之前是通过数据源获取屏蔽日期来实现禁用功能的,现在突然不管用了——哪怕直接写个内联的tileDisabled函数都没效果,比如:
<DatePicker tileDisabled={({ activeStartDate, date, view }) => date.getDay() === 0} />
我已经试过不少排查手段了:把旧网站的代码注释掉重新构建(旧网站是正常工作的)、改用内联函数、执行gatsby clean清理缓存、重新安装所有依赖包,但就是搞不懂为什么日期 tiles 没法被禁用。
有没有朋友遇到过类似的情况?或者知道问题可能出在哪、该怎么进一步排查?另外如果有好用的替代日历组件也欢迎推荐!
完整页面代码
import React, {useRef, useEffect, useState} from "react" import styled from "@emotion/styled" import { useForm } from "react-hook-form" import ReCAPTCHA from "react-google-recaptcha"; import { navigate } from "gatsby"; import { isWithinInterval } from "date-fns"; import DatePicker from 'react-date-picker' import 'react-date-picker/dist/DatePicker.css'; import 'react-calendar/dist/Calendar.css'; const FormDiv = styled.div` width: 694px; // margin-right: 100px; box-sizing: border-box; display: flex; justify-content: center; align-items: center; form { // padding: 50px; width: 694px; // margin-right: 20px; // max-width: 800px; min-height: 500px; height: 100%; max-height: 800px; // background-color: white; border-radius: 2px; display: flex; flex-direction: column; justify-content: center; .select-style { // background-color: white; padding: 5px; border: solid 1px black; :hover { cursor: pointer; } } .button-style { margin-top: 40px; padding: 20px; background-color: white; color: black; border: none; border-radius: 10px; font-size: 14px; font-weight: 600; transition: .3s; :hover { cursor: pointer; // background-color: #635bff; } } .back { width: 28%; margin-right: 2%; } .next { width: 70%; } label { font-weight: 600; margin-top: 50px; // margin-left: 10px; margin-bottom: 4px; } input{ font-size: 20px; padding: 15px; background-color: black; color: white; border-radius: 10px; border: 2px solid rgba(255,255,255,1); transition: .3s; } // input:hover { // border: 1px solid rgba(0,0,0,0.5); // } input:focus-visible, textarea:focus-visible { border: 2px solid rgba(255,255,255,0.5); outline: 0; } } .time-selection { display: flex; flex-wrap: wrap; // justify-content: space-between; div { // border: solid 2px white; border: 2px solid rgba(255,255,255,0.2); border-radius: 10px; font-size: 16px; font-weight: 600; padding: 14px 14px; box-shadow: rgba(0, 0, 0, 0.12) 0px 1px 3px, rgba(0, 0, 0, 0.24) 0px 1px 2px; margin: 0 10px 10px 0; transition: .3s; // background-color: grey; :hover { cursor: pointer; border: 2px solid rgba(255,255,255,0.5); } } .active-time { background-color: white; color: black; } } .grecaptcha-badge { visibility: hidden!important; } .recaptcha-sub { font-size: 14px; color: hsla(40,22%,92%,.6); } .react-date-picker__wrapper { width: 100%; padding: 15px; font-size: 20px; padding: 15px; background-color: black; color: white; border-radius: 10px; // border: 2px solid rgba(255,255,255,1); border: 2px solid rgba(255,255,255,0.2); -webkit-transition: .3s; transition: .3s; :hover { cursor: pointer; border: 2px solid rgba(255,255,255,0.5); } input { border: none; } input:focus-visible { border: none; } } .react-date-picker__calendar-button__icon, .react-date-picker__clear-button__icon { stroke: white; transition: .3s; } .react-date-picker__inputGroup__input { padding: 0; } @media(max-width: 940px){ width: 90vw!important; form { box-sizing: border-box; width: 90vw!important; } ` // function isWithinRange(date, range) { // console.log("isWithinRangeRunning", date, range) // return isWithinInterval(date, { start: range[0], end: range[1] }); // } // function isWithinRanges(date, ranges) { // console.log("isWithinRangesRunning", date, ranges) // return ranges.some(range => isWithinRange(date, range)); // } // let in3Days = new Date(2024, 11, 28); // let in5Days = new Date(2024, 11, 28); // let in13Days = new Date(2024, 11, 30); // let in15Days = new Date(2024, 11, 31); // let testDays = new Date(2024, 12, 26); function isWithinRange(date, range) { console.log("isWithinRangeRunning") return isWithinInterval(date, { start: range[0], end: range[1] }); } function isWithinRanges(date, ranges) { console.log("isWithinRangesRunning") return ranges.some(range => isWithinRange(date, range)); } let in3Days = new Date(2025, 1, 28); let in5Days = new Date(2025, 1, 28); let in13Days = new Date(2025, 1, 26); let in15Days = new Date(2025, 1, 26); export default function ContactElectrical({datesUnavailable, setFormStage, timesAvailable, totalPrice, name, phone, email, adults, youth, lessonString, gearString, bikeString, hourString}){ ///need to reformat dates here before adding to state, or do in useEffect const reRef = useRef(); const [selectedDate, updateSelectedDate] = useState(new Date()); const [serverState, setServerState] = useState({formSent: false}); const [activeTime, setActiveTime] = useState(0) const [bookedDates, setBookedDates] = useState([ [in3Days, in5Days],[in13Days, in15Days],]) // const [bookedDates, setBookedDates] = useState([ [in3Days, in5Days],[in13Days, in15Days],]) console.log("datesUnavailable: ", datesUnavailable) // console.log("booked", bookedDates) useEffect(()=> { console.log("dates Unavailable running") let datesUnavailableRanges = [] for(let i = 0; i < datesUnavailable.length; i++){ let d = datesUnavailable[i].bookedDate.split("/") //except here they need to be in the right format so I need to seperate and make it so it's like this: new Date(2023, 11, 26); datesUnavailableRanges.push([new Date(Number(d[2]), Number(d[1])-1, Number(d[0])), new Date(Number(d[2]), Number(d[1])-1, Number(d[0]))]) } setBookedDates(datesUnavailableRanges); },[datesUnavailable]) // console.log("booked", bookedDates) console.log("tile", tileDisabled({date: in3Days, view: "month"})) // function tileDisabled({ date, view}) { // console.log("test", view) // console.log("date", date) // console.log("test2", bookedDates) // // Add class to tiles in month view only // if (view === 'month') { // // Check if a date React-Calendar wants to check is within any of the ranges // console.log("test3", isWithinRanges(date, bookedDates)) // return isWithinRanges(date, bookedDates); // } // } function tileDisabled({ date, view}) { // Add class to tiles in month view only if (view === 'month') { // Check if a date React-Calendar wants to check is within any of the ranges return isWithinRanges(date, bookedDates); } } const { register, handleSubmit, formState: { errors }, } = useForm() async function onSubmit(data){ // const reRef = useRef<>(); const token = await reRef.current.executeAsync(); reRef.current.reset(); let dd = selectedDate.getDate(); let mm = selectedDate.getMonth()+1; let yyyy = selectedDate.getFullYear(); let reformattedDate = dd+"/"+mm+"/"+yyyy; fetch("/api/postmark-booking", { method: `POST`, body: JSON.stringify({ name: name, email: email, phone: phone, adults: adults, youth: youth, lesson: lessonString, date: reformattedDate, time: timesAvailable[activeTime].time, gear: gearString, bike: bikeString, hours: hourString, totalPrice: totalPrice, token, }), headers: { "content-type": `application/json`, }, }) .then(res => res.json()) .then(body => { console.log(`response from API:`, body); }) .then(setServerState({formSent: true})) } console.log({ errors }) useEffect(() => { if (serverState.formSent === true) { navigate("/booking-success/"); setTimeout(() => { setServerState({ formSent: false }) }, 3000) } }) return ( <FormDiv> <ReCAPTCHA sitekey={process.env.GATSBY_RECAPTCHA_SITE_KEY} ref={reRef} size="invisible" /> <form onSubmit={handleSubmit(onSubmit)}> <label htmlFor="date">Select Date</label> <DatePicker onChange={updateSelectedDate} value={selectedDate} tileDisabled={tileDisabled} /> <label htmlFor="time">Select Time</label> <div className="time-selection"> {timesAvailable.map((time, index) => ( <div key={index} className={activeTime === index ? "active-time" : ""} onClick={() => setActiveTime(index)} > {time.time} </div> ))} </div> <div style={{display: "flex", marginTop: "40px"}}> <button className="button-style back" onClick={() => setFormStage(2)}>Back</button> <input type="submit" className="button-style next" value="Confirm and Book" /> </div> <p className="recaptcha-sub">This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.</p> </form> </FormDiv> ) }
备注:内容来源于stack exchange,提问作者Daniel Balloch
相关产品推荐
相关产品推荐

