1
votes

A reproducible example can be found in this link.

I'm starting with React and Hooks. Currently, I'm trying to build a configuration form to generate some reports. The first sub-component of my entire form that I'm building is a Filter component with only two dates (start and end dates).

In the outer component called Configuration I have the form state and the start and end dates are passed by props to the Filter component as well the onPeriodChange callback:

export const Configuration: React.FC = () => {
  const [periodState, setPeriodState] = useState<Period>({
    startDate: '',
    endDate: '',
  });

  const handlePeriodChange = useCallback(
    (field: keyof Period, value: string) =>
      setPeriodState({ ...periodState, [field]: value }),
    [periodState],
  );

  return (
    <MuiPickersUtilsProvider utils={DateFnsUtils}>
      <form name="configuration">
        <Filters period={periodState} onPeriodChange={handlePeriodChange} />
      </form>
    </MuiPickersUtilsProvider>
  );
};

Then, the props are passed to KeyboardDatePicker components in the Filter components:

export const Filters: React.FC<FilterProps> = (filterProps: FilterProps) => {
  const { period, onPeriodChange } = filterProps;

  return (
    (...)
      <KeyboardDatePicker
        disableToolbar
        fullWidth
        variant="inline"
        format="dd/MM/yyyy"
        id="start-date"
        label="Data de descarga inicial:"
        value={period.startDate}
        onChange={(date) => {
          onPeriodChange(
            'startDate',
            date instanceof Date && !Number.isNaN(date)
              ? date.toISOString()
              : '',
          );
        }}
        required
        KeyboardButtonProps={{
          'aria-label': 'change date',
        }}
      />
    (...)
  );
};

In the first render, the components are displayed as invalid:

Invalid components

And when I change the value of the first component I'm getting a console warning saying (you can reproduce this behavior in the sandbox):

Warning: A component is changing an uncontrolled input to be controlled. This is likely caused by the value changing from undefined to a defined value, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component.

I don't know why I'm getting this error, since the initial values of the start and end date are an empty string (and not undefined). Can you point me where is my mistake? Thanks!

1
Have you tried debugging it to see if the values really is undefined at any point in time? Also - You can avoid the dependency in your useCallback hook by using a functional update - Jason

1 Answers

1
votes

This is because the period value changes from an empty string to a Date, in your initial value, you should also pass a Date.

Warning: A component is changing an uncontrolled input to be controlled. This is likely caused by the value changing from undefined to a defined value, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component.

Interface update

export interface Period {
  startDate: Date;
  endDate: Date;
}

Initial state update

const [periodState, setPeriodState] = useState<Period>({
    startDate: new Date(Date.now()),
    endDate: new Date(Date.now())
  });

Sandbox update