Learning4Ever
Learning4Ever

Reputation: 45

React Hook Form: display input content while user typing

I created a React Hook Form and a div to display the data. I want to display the input value as a user type. I can do this with onChange, but I had a problem when I use react-hook-form.

If I tried to add onChange after the {...register()}, it will work, but the error message will not go away if the input is empty. Is there a possible way to do this?

import "./styles.css";
import { useState } from "react";
import { useForm } from "react-hook-form";

const initalState = {
  name: "test",
  description: "test description"
};

export default function App() {
  const [info, setInfo] = useState(initalState);

  const handleFormSubmit = (data) => {
    setInfo(data);
    console.log(data);
  };

  const handleFormChange = (event) => {
    console.log(event.target.value);
    setInfo({
      ...info,
      [event.target.name]: event.target.value
    });
  };

  return (
    <div className="App">
      <div style={{ textAlign: "left" }}>
        <p>Name: {info.name}</p>
        <p>Description {info.description}</p>
      </div>
      <Form
        handleFormSubmit={handleFormSubmit}
        handleFormChange={handleFormChange}
      />
    </div>
  );
}

const Form = ({ handleFormSubmit, handleFormChange }) => {
  const {
    register,
    handleSubmit,
    formState: { errors }
  } = useForm();
  return (
    <form onSubmit={handleSubmit(handleFormSubmit)}>
      <label htmlFor="name">Name: </label>
      <input id="name" {...register("name", { required: "Can't be blank" })} />
      <p style={{ color: "red" }}>{errors.name?.message}</p>
      <label htmlFor="description">Description: </label>
      <input
        id="description"
        {...register("description", { required: "Can't be blank" })}
      />
      <p style={{ color: "red" }}>{errors.description?.message}</p>
      <button type="submit">Submit</button>
    </form>
  );
};

Upvotes: 2

Views: 1506

Answers (1)

Youssouf Oumar
Youssouf Oumar

Reputation: 45835

You can use a subscription with watch function returned by useForms(). For that, first change handleFormChange to:

const handleFormChange = useCallback(
  (value, name) => {
    setInfo({ ...info, [name]: value[name] });
  },
  [info]
);

And then, in Form component, do this:

const {
  register,
  handleSubmit,
  watch,
  formState: { errors }
} = useForm();

useEffect(() => {
  const subscription = watch((value, { name, type }) => {
    console.log(value, name);
    handleFormChange(value, name);
  });
  return () => subscription.unsubscribe();
}, [watch, handleFormChange]);

Upvotes: 1

Related Questions