Форма React Hook с datepicker Range не выбирает дату
У меня есть следующие датпикеры.
Для даты начала:
<Controller
as={
<DatePicker
selected={travelRoute?.dateStart || new Date()}
selectsStart
startDate={travelRoute?.dateStart}
endDate={travelRoute?.dateEnd}
inline
/>
}
control={control}
rules={{ required: true }}
valueName="selected"
onChange={date => handleStartDateOnChange(date)}
name="dateStart"
placeholderText="Select date"
defaultValue={null}
/>
На дату окончания:
<Controller
as={
<DatePicker
name="dateEnd"
selected={travelRoute?.dateEnd || new Date()}
onChange={date => handleEndDateOnChange(date)}
selectsEnd
startDate={travelRoute?.dateStart}
endDate={travelRoute?.dateEnd}
minDate={travelRoute?.dateStart}
inline
/>
}
control={control}
rules={{ required: true }}
valueName="selected"
onChange={date => handleEndDateOnChange(date)}
name="dateEnd"
placeholderText="Select date"
defaultValue={null}
/>
Нужно ли мне добавлять реквизиты datepicker в компонент datepicker или в компонент контроллера?
Начальный Datepicker не выбирает дату, а конечный Datepicker не изменяет начальную дату и не отображает диапазон.
Я сохраняю данные в состоянии travelRoute с помощью setTravelRoute, что происходит в функциях handleOnChange.
РЕДАКТИРОВАТЬ:
добавлен обработчик onChange:
const handleStartDateOnChange = date => {
setTravelRoute(prevState => ({
...prevState,
dateStart: date
}))
};
const handleEndDateOnChange = date => {
setTravelRoute(prevState => ({
...prevState,
dateEnd: date
}))
};
2 ответа
Чао, вы используете неправильный подход к настройке своего onChange
событие в DatePicker
. А такжеonChange
событие на Controller
не может работать neihter. Потому что в этом случае вам не нужно использоватьas=
синтаксис, но render=
синтаксис вроде:
<Controller
render={({ onChange }) => (
<DatePicker
...
onChange={date => handleStartDateOnChange(date)}
/>
)}
...
/>
Итак, ваш код становится:
Дата начала
<Controller
render={({ onChange }) => (
<DatePicker
selected={travelRoute?.dateStart || new Date()}
selectsStart
startDate={travelRoute?.dateStart}
endDate={travelRoute?.dateEnd}
inline
onChange={date => handleStartDateOnChange(date)}
/>
)}
control={control}
rules={{ required: true }}
valueName="selected"
name="dateStart"
placeholderText="Select date"
defaultValue={null}
/>
Дата окончания
<Controller
render={({ onChange }) => (
<DatePicker
name="dateEnd"
selected={travelRoute?.dateEnd || new Date()}
onChange={date => handleEndDateOnChange(date)}
selectsEnd
startDate={travelRoute?.dateStart}
endDate={travelRoute?.dateEnd}
minDate={travelRoute?.dateStart}
inline
/>
)}
control={control}
rules={{ required: true }}
valueName="selected"
name="dateEnd"
placeholderText="Select date"
defaultValue={null}
/>
Вот рабочий пример.
Примечание: я не знаю почему DatePicker
в codeandbox выглядит так некрасиво. Может бытьController
потому что в этом коде выглядит хорошо.
У меня был другой подход к решению этого вопроса и я хотел им поделиться.
Я ответил на некоторые связанные вопросы в следующем сообщении: https://stackoverflow.com/a/72585781/19320134
В любом случае, один из способов сделать код более пригодным для повторного использования — поместить эти контроллеры в отдельные файлы, чтобы при их вызове импортировалось только имя функции.
export const DateRange = ({ name, control, label }) => {
const [dateRange, setDateRange] = useState([null, null]);
const [startDate, endDate] = dateRange;
return (
<Controller
//is a prop that we get back from the useForm Hook and pass into the input.
control={control}
//is how React Hook Form tracks the value of an input internally.
name={name}
//render is the most important prop; we pass a render function here.
render={({
//The function has three keys: field , fieldState, and formState.
field, // The field object exports two things (among others): value and onChange
}) => (
<>
<DatePicker
selectsRange={true}
startDate={startDate}
endDate={endDate}
onChange={(e) => {
setDateRange(e);
field.onChange(e);
}}
isClearable={true}
className="form-control"
/>
</>
)}
rules={{
required: `The ${label} field is required`,
}}
/>
И вы можете вызвать его в нужном файле следующим образом
import { useForm, Controller, FormProvider } from "react-hook-form";
import {DateRange} from "./your file !"
const defaultValues = {
dateRange: [],
};
export default function ComponentUsingDateRange() {
const methods = useForm({
defaultValues,
mode: "onChange",
});
const { register, handleSubmit, control, setValue } = methods;
return(
<>
<FormProvider {...methods}>
<DateRange
control={control}
name="dateRange"
label="Range of dates"
/>
</FormProvider>
</>
);
}