Форма 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>
     </>
       
     );
}
Другие вопросы по тегам