React-datepicker with custom input with manual typing

Viewed 104

I am trying to create react-datepicker component with custom styled input:

<DatePicker
        selected={startDate}
        customInput={<CustomInput inputRef={inputRef} />}
        onChangeRaw={(e) => handleChangeRaw(e)}
        onChange={(date: Date | null) => {
          setStartDate(date);
        }}
      />

const CustomInput = forwardRef((props: any, ref) => {
  return <Input {...props} ref={ref} />;
});

I wanted to introduce validation (just simple validation that whatever user inputs will be formatted to the date so user cannot just type whatever he wants).

I created a function that would be formatting the input using onChangeRaw attribute in react-datepicker:

  const handleChangeRaw = (date) => {
    date.currentTarget.value = format(startDate, "dd/MM/yyyy");
  };

However after using this I cannot type anymore. Anyone has idea how to use manual typing with custom input in react-datepicker with simple validation function?

Here is recreated issue in the sandbox: https://codesandbox.io/s/react-datepicker-custominput-sample-forked-elx310?file=/src/App.tsx

2 Answers
selected={startDate}

Here react-datepicker expects a Date object.

However, when you trigger handleChangeRaw, you get an change event, with some value (date.currentTarget.value), but thats not in the Date notation that datepicker expects.

So my take on this would be;

  • onChangeRaw, convert the input value to a new Date.
  • If the date isn't valid, just ignore the change
  • Otherwise, create a new Date, and use setStartDate to change to that new date
const handleChangeRaw = (date) => {
      const newRaw = new Date(date.currentTarget.value);
      if (newRaw instanceof Date && !isNaN(newRaw)) {
        setStartDate(newRaw);
      }
  };

Try it online

If I understand your issue correctly, you can add the following type to fix the typing.

const handleChangeRaw = (date: React.FocusEvent<HTMLInputElement>) => {
    if (!startDate){
      return
    }
    date.currentTarget.value = format(startDate, "dd/MM/yyyy");
};

date should have the type React.FocusEvent<HTMLInputElement>. Since startDate can be null, we have to check before using it. In this case I just return from the function. But you could also assign a default value here or something else.

Related