Error: A component is changing an uncontrolled input to be controlled.

2024/04/11に公開

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.

フォーム要素に対して、「コンポーネントが非制御から制御に変わってるよ。制御コンポーネントとして扱うのか非制御コンポーネントとして扱うのかはっきりしなよ」って言われました。
制御コンポーネントとして扱ってるつもりなんやけどな・・・

書いてたのは以下のようなコード。shadcnの date-picker のデータ表示部分を、spanからinputに変えている。問題がそこなのはわかる

...省略

const formattedDate = () => {}...省略: date fnsとかそんなんのラッパ

type Props = {
  inputProps?: React.DetailedHTMLProps<
    React.InputHTMLAttributes<HTMLInputElement>,
    HTMLInputElement
  >;
  date: Date | undefined;
  setDate: DayPickerSingleProps['onSelect'];
};

export const DatePicker = ({ inputProps, date, setDate }: Props) => {
  return (
    <Popover>
      <PopoverTrigger asChild>
        <input
          readOnly
          value={date && formattedDate(date)}
          {...inputProps}
        />
      </PopoverTrigger>
      <PopoverContent className="w-auto p-0">
        <Calendar
          mode="single"
          selected={date}
          onSelect={setDate}
          initialFocus
        />
      </PopoverContent>
    </Popover>
  );
};

結論

これで直った。

...省略

const formattedDate = () => {}...省略: date fnsとかそんなんのラッパ

type Props = {
  inputProps?: React.DetailedHTMLProps<
    React.InputHTMLAttributes<HTMLInputElement>,
    HTMLInputElement
  >;
  date: Date | undefined;
  setDate: DayPickerSingleProps['onSelect'];
};

export const DatePicker = ({ inputProps, date, setDate }: Props) => {
  return (
    <Popover>
      <PopoverTrigger asChild>
        <input
          readOnly
          value={date ? formattedDate(date): ""}
          {...inputProps}
        />
      </PopoverTrigger>
      <PopoverContent className="w-auto p-0">
        <Calendar
          mode="single"
          selected={date}
          onSelect={setDate}
          initialFocus
        />
      </PopoverContent>
    </Popover>
  );
};

value={date && formattedDate(date)}value={date ? formattedDate(date): ""}に変えている

なるほどな〜。この、dateがないときにundefindをvalueに渡してしまうこと = 制御・非制御が変化しちゃってるってことなのか。

おしまい⭐

Discussion