Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 646
Raphael Prado de Oliveira Avatar asked May 27 '20 16:05

Raphael Prado de Oliveira


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

like image 123
Vivek Doshi Avatar answered Nov 17 '22 11:11

Vivek Doshi