Как отправлять поля формы реакции на onChange, а не на отправку, используя библиотеку React-Hook-Form

Я начал использовать новую библиотеку форм React-Hook и хотел отправить свои поля ввода на Change, а не на Submit. Кроме того, я планирую использовать debounce от Lodash, чтобы избежать повторного рендеринга

Это то, что я пробовал до сих пор:

import React, { useEffect } from "react";
import ReactDOM from "react-dom";
import { useForm } from "react-hook-form";

import "./styles.css";

export default function App() {
  const { register, handleSubmit, setValue } = useForm();
 

  useEffect(() => {
    register({ name: "firstName" }, { required: true });
  }, [register]);

  return (
    <form>
      <input
        name="firstName"
        onChange={(e) => {
          setValue("firstName", e.target.value);
          handleSubmit((data) => console.log("data", data));
        }}
      />
    </form>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

7 ответов

Я нашел самый простой способ:

      const { handleSubmit, watch } = useForm();
const onSubmit (data) => console.log(data)

useEffect(() => {
    const subscription = watch(() => handleSubmit(onSubmit)());
    return () => subscription.unsubscribe();
}, [watch]);

Если вы зарегистрируете свою реализацию handleSubmit внутри onChange, вы заметите, что он возвращает функцию

Попробуйте вызвать возвращенную функцию, и она должна быть отправлена.

onChange={(e) => {
    setValue("firstName", e.target.value);
    handleSubmit((data) => console.log("data", data))();
}}

Я также недавно написал свою версию реализации "пользователь закончил ввод, затем отправил" для полей ввода - проверьте это: /questions/53605058/est-li-sposob-otpravit-poiskovyij-zapros-v-react-tolko-kogda-kto-to-perestaet-pe/53605061#53605061

Из вашего примера похоже, что вы хотите получить (все) значения только после изменения ввода. Не уверен, что это поможет вам, но вы можете использовать getValues функция от useForm крюк.

      const Filters: FC<TProps> = ({ filters, setActiveFilter }) => {
  const { register, getValues } = useForm();

  const handleChange = () => {
    const values = getValues();
    // Do something with values, in my case I have used the 'setActiveFilter' function above.
  };

  return (
    <form>
      {filters.map((filter) => (
        <fieldset key={filter.id}>
          <legend>{filter.label}</legend>
          {filter.options.map((option) => (
            <label htmlFor={option.value} key={option.id}>
              <input
                type="checkbox"
                id={option.value}
                name={filter.label}
                value={option.id}
                ref={register}
                onChange={handleChange}
              />
              {option.value}
            </label>
          ))}
        </fieldset>
      ))}
    </form>
  );
};

Ответ Алекса не работает в моем случае, так как мне нужна небольшая задержка перед отправкой формы (когда пользователь перестал печатать)

Вот мое решение

const { handleSubmit, watch } = useForm();const onSubmit = (данные) => console.log(данные);

      useEffect(() => {
 const subscription = watch(() => {
   if (timer) clearTimeout(timer);

   timer = setTimeout(() => {
     handleSubmit(onSubmit)();
   }, 1000);
 });
 return () => subscription.unsubscribe();
}, [handleSubmit, watch]);

в формах реагирования на крючки watch - это альтернативный способ onChange, просто сделайте это:

      const handleSubmit = (data) => {
 console.log(data)
}
    const {watch} = useForm();
    
          watch((data, { name }) => {
            if (name === "firstName") handleSubmit(data);
          });

Мои два цента за решение, которое может быть ориентировано на полную форму. Я просто использую onChange в теге формы, и это просто работает. Вы также можете довольно легко отменить его в глобальном масштабе.

      debounce(handleSubmit((data) => console.log("data", data)), 1500)

Почему вы хотите отправить его на Change?

но если вы действительно хотите это сделать, это должно сработать:

import React, { useEffect } from "react";
import ReactDOM from "react-dom";
import { useForm, useWatch } from "react-hook-form";

import "./styles.css";

export default function App() {
  const { register, control, handleSubmit } = useForm()
  const firstName = useWatch({ control, name: 'firstName' })

  useEffect(() => {
    if(firstName && firstName.length > 0) {
      handleSubmit(data => console.log("data", data))()
    }
  }, [firstName, handleSubmit])

  return (
    <form>
      <input ref={register({ required: true })} name="firstName" />
    </form>
  )
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Другие вопросы по тегам