sanManjiro
@sanManjiro

Почему не работает валидации при установке значения в rect-hook-form?

Компонент:
spoiler
import {
  Controller,
  Control,
  FieldErrors,
  FieldValues,
  FieldPath,
} from "react-hook-form";

// UTILITIES
import { getErrorMessage } from "@utilities/getErrorMessage";

// STYLES
import style from "./input-error-message.module.scss";

export interface IInputOuCode<T extends FieldValues> {
  controller: {
    control: Control<T>;
    name: FieldPath<T>;
  };
  customClassName?: string;
  value: T[keyof T];
  id?: string;
  name?: string;
  placeholder: string;
  error: FieldErrors<T>;
  errorMessage: string;
  onChange: (event: any) => void;
  onClick?: (event: React.MouseEvent<HTMLInputElement>) => void;
  onFocus?: (event: React.FocusEvent<HTMLInputElement>) => void;
  onBlur?: (event: React.FocusEvent<HTMLInputElement>) => void;
  onKeyDown?: (Event: React.KeyboardEvent<HTMLInputElement>) => void;
}

// export function formatOuCode(value: string): string {
//   let numericValue = value.replace(/\D/g, "");

//   numericValue = numericValue.slice(0, 6);

//   let formattedValue = "";
//   if (numericValue.length > 0) {
//     formattedValue += numericValue.slice(0, 3);
//     if (numericValue.length > 3) {
//       formattedValue += `-${numericValue.slice(3)}`;
//     }
//   }

//   return formattedValue;
// }

export default function InputOuCode<T extends FieldValues>(
  props: IInputOuCode<T>
): JSX.Element {
  const errorMessage = getErrorMessage(props.error, props.controller.name);

  return (
    <div className={style.formInput}>
      <Controller
        control={props.controller.control}
        name={props.controller.name}
        defaultValue={props.value}
        rules={{
          required: "*Необходимо заполнить поле",
          minLength: {
            value: 6,
            message: "*Необходимо заполнить полностью код подразделения",
          },
        }}
        render={({ field }) => (
          <input
            value={props.value}
            className={`custom-input ${props.customClassName}`}
            type="text"
            placeholder={props.placeholder}
            maxLength={6}
            onChange={(val) => {
              const formattedValue = val.target.value;

              field.onChange(formattedValue);
              props.onChange(formattedValue);
            }}
            onClick={props.onClick}
            onFocus={props.onFocus}
            onBlur={(event) => {
              props.onBlur?.(event);
              field.onBlur();
            }}
            onKeyDown={props.onKeyDown}
          />
        )}
      />
      <p className={`${style.errorMessage} form-error-message`}>
        {errorMessage && <span>{errorMessage}</span>}
      </p>
    </div>
  );
}

Его вызов:
spoiler
<div className={`${style["pass-details__field__ou-code"]}`}>
          <InputOuCode<IDataFormPassport>
            controller={{
              control: control,
              name: "ouCode",
            }}
            value={dataFormPassport.ouCode}
            placeholder="Код подразделения"
            error={errors}
            errorMessage="*Заполните полностью код подразделения"
            onChange={handleOuCodeOnChange}
            onClick={handleOuCodeOnClick}
            onBlur={() => {
              setTimeout(() => {
                resetHints();
              }, 200);
            }}
          />
          {hints.key === "ouCode" &&
            Array.isArray(hints.dataFmsUnit) &&
            hints.dataFmsUnit.length > 0 && (
              <ul className={`${style["pass-details__field__ou-code__list"]}`}>
                {hints.dataFmsUnit.map((suggestion, index) => (
                  <li
                    key={index}
                    className={`${style["pass-details__field__ou-code__item"]}`}
                    onClick={() => handleOuCodeSelectOnClick(suggestion)}
                  >
                    {suggestion.value}
                  </li>
                ))}
              </ul>
            )}
        </div>

Все обработчики:
spoiler
// NOTE: Обработка и получение адресов при вводе
  const handleOuCodeOnChange = async (val: string) => {
    console.log("val", val);
    
    const sliceList = 5;
    try {
      const fmsUnitList = await getFmsUnit(val, sliceList);
      const fmsUnitProps = fmsUnitList[0]?.data || {};

      setHints({
        dataFmsUnit: fmsUnitList,
        key: "ouCode",
      });

      updateDataForm({
        ouCode: val,
        placeOfIssue: fmsUnitProps.name || "",
      });
    } catch (error) {
      console.error("ОШИБКА В ONCHANGE ПРИ ОБРАБОТКЕ АДРЕСОВ:", error);
    }
  };

  // NOTE: Получение списка адресов при клике
  const handleOuCodeOnClick = async () => {
    const sliceList = 5;
    try {
      const fmsUnitList = await getFmsUnit(dataFormPassport.ouCode, sliceList);
      setHints({
        dataFmsUnit: fmsUnitList,
        key: "ouCode",
      });
    } catch (error) {
      console.error("ОШИБКА В ONCLICK ПРИ НАЖАТИИ НА ПОЛЕ:", error);
    }
  };

  // NOTE: Обработка клика выбранного адреса
  const handleOuCodeSelectOnClick = (suggestion: IFmsUnitDate) => {
    resetHints();

    console.log("suggestion", suggestion);
    
    const newOuCode = suggestion.data.code.replace(/\D/g, "");

    updateDataForm({
      ouCode: newOuCode,
      placeOfIssue: suggestion.data.name,
    });
    console.log("click:", newOuCode);
    console.log("getValues:", getValues("ouCode"));
  };

spoiler
// NOTE: Обновление данных формы
  const updateDataForm = (newData: Partial<IDataFormPassport>) => {
    const updatedData = { ...dataFormPassport, ...newData };

    setDataFormPassport(updatedData);
    setStoredData(StorageKeys.PASSPORT_INFO, updatedData);
  };

  // NOTE: Сброс подсказок
  const resetHints = () => {
    setHints({
      dataAddress: [],
      dataFmsUnit: [],
      key: "",
    });
  };
  • Вопрос задан
  • 41 просмотр
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы