Datepicker component breaking an edit screen, using @unform and react-datepicker

Viewed 927

I created the following component to select dates in UnForm:

export default function DatePickerInput({ name, ...rest }) {
  const datepickerRef = useRef(null);
  const { fieldName, defaultValue = '', registerField } = useField(name);

  const [date, setDate] = useState(defaultValue || null);
  useEffect(() => {
    registerField({
      name: fieldName,
      ref: datepickerRef.current,
      path: 'props.selected',
    });
  }, [fieldName, registerField]);

  return (
    <Label htmlFor={fieldName}>
      <UnInput>
        <ReactDatePicker
          ref={datepickerRef}
          selected={date}
          onChange={setDate}
          dateFormat="dd/MM/yyyy"
          placeholderText="dd/mm/aaaa"
          writable="true"
          {...rest}
        />
      </UnInput>
    </Label>
  );
}

To save records the component is working normally, loading and saving the date I selected. When I am going to edit a record, when trying to load the date in the initial load, the page is broken and the following error is displayed:

Unhandled Rejection (TypeError): Cannot assign to read only property 'selected' of object '#<Object>'

If I comment out the line path: 'props.selected', in useEffect () the screen is not broken, but the date is not filled in the component. How do it work?

1 Answers

Issue :

formRef.current.setFieldValue('birthday',value) this will try to set value on provided path , in our case provided path is props.selected.

And props.selected is read-only property so you can't set value on props hence the error.

useEffect(() => {
    registerField({
      name: fieldName,
      ref: datepickerRef.current,
      path: 'props.selected', // <---- this is props, and it's readonly
      clearValue: (ref) => {
        ref.clear();
      },
    });
}, [fieldName, registerField]);

Solution :

You can remove the path and use getter and setter methods, named as getValue and setValue :

setValue : to set the initial value or whatever passed from setFieldValue

getValue : to get value on submit

useEffect(() => {
    registerField({
      name: fieldName,
      ref: datepickerRef.current,
      clearValue: ref => {
        ref.clear();
      },
      setValue: (e, v) => {
        setDate(new Date(v)); // <---- Setting up default value 
      },
      getValue: () => {
        return datepickerRef.current.props.selected; // to get selected value from Date picker's props
        // OR
        return Date.toString(); // to get selected value from state it self
      }
    });
}, [fieldName, registerField]);

WORKING DEMO :

Edit #SO-Datepicker-unform-setvalue

Related