Next.js Discord

Discord Forum

pull data from form

Unanswered
Harlex posted this in #help-forum
Open in Discord
I have 3 different form components, I want to get the data from these forms and send a request to the API by clicking the button in my main component, everything is ok, I just don't know how to get the data from the forms.

5 Replies

ExampleForm.tsx
import Input from "@/app/components/ui/Forms/Input";
import Textarea from "@/app/components/ui/Forms/Textarea";
import { AddressFormInputProps } from "@/app/types/props/form/AddressFormInputProps";
import { forwardRef, useImperativeHandle } from "react";
import { useForm } from "react-hook-form";
import { FaFlag, FaTag } from "react-icons/fa6";

const AddressForm = forwardRef((props, ref) => {
  const {
    register,
    getValues,
    formState: { errors },
  } = useForm<AddressFormInputProps>();

  useImperativeHandle(ref, () => ({
    getValues,
  }));

  return (
    <>
      <div className="mb-5">
        <h2 className="text-xl font-semibold mb-1">Adres Bilgileri</h2>
      </div>
      <form>
        <div className="grid grid-cols-1 md:grid-cols-2 gap-5 mb-5">
          <Input
            placeholder="Ülke Yazınız"
            label="Ülke"
            iconElement={<FaFlag />}
            register={register}
            name="country"
            rules={{
              required: "Ülke alanını doldurmak zorunludur.",
            }}
            error={errors.country?.message}
          />
          <Input
            placeholder="İl Yazınız"
            label="İl"
            iconElement={<FaFlag />}
            register={register}
            name="c"
            rules={{
              required: "İl alanını doldurmak zorunludur.",
            }}
            error={errors.city?.message}
          />
        </div>
    {...inputs}        
      </form>
    </>
  );
});

AddressForm.displayName = "AddressForm";

export default AddressForm;
Main.tsx
"use client";

import { useRef, useState } from "react";
import UserForm from "./userForm/UserForm";
import AddressForm from "./addressForm/AddressForm";
import UserPassword from "./userPassword/UserPassword";
import Button from "@/app/components/ui/Buttons/Button";
import Tab from "@/app/components/shadcn/Tab";
import { useDispatch } from "react-redux";
import { AppDispatch } from "@/app/redux/store";
import { postUser } from "@/app/redux/features/userSlice";

const UserTab = () => {
  const dispatch: AppDispatch = useDispatch();

  const userFormRef = useRef<any>(null);
  const addressFormRef = useRef<any>(null);
  const passwordFormRef = useRef<any>(null);

  const handleUserAdd = async () => {
    if (
      userFormRef.current &&
      addressFormRef.current &&
      passwordFormRef.current
    ) {
      const formData = {
        ...userFormRef.current.getValues(),
        ...addressFormRef.current.getValues(),
        ...passwordFormRef.current.getValues(),
      };

        await dispatch(postUser(formData)).unwrap();

    }
  };

  return (
    <>
      <Tab
        tabs={[
          {
            label: "Profil",
            value: "profile",
            content: <UserForm ref={userFormRef} />,
          },
          {
            label: "Adres",
            value: "address",
            content: <AddressForm ref={addressFormRef} />,
          },
          {
            label: "Şifre",
            value: "password",
            content: <UserPassword ref={passwordFormRef} />,
          },
        ]}
        defaultValue="profile"
      />
      <div className="mt-5 flex justify-end">
        <Button onClick={handleUserAdd} type="submit" content="Oluştur" />
      </div>
    </>
  );
};

export default UserTab;
@Harlex ExampleForm.tsx tsx import Input from "@/app/components/ui/Forms/Input"; import Textarea from "@/app/components/ui/Forms/Textarea"; import { AddressFormInputProps } from "@/app/types/props/form/AddressFormInputProps"; import { forwardRef, useImperativeHandle } from "react"; import { useForm } from "react-hook-form"; import { FaFlag, FaTag } from "react-icons/fa6"; const AddressForm = forwardRef((props, ref) => { const { register, getValues, formState: { errors }, } = useForm<AddressFormInputProps>(); useImperativeHandle(ref, () => ({ getValues, })); return ( <> <div className="mb-5"> <h2 className="text-xl font-semibold mb-1">Adres Bilgileri</h2> </div> <form> <div className="grid grid-cols-1 md:grid-cols-2 gap-5 mb-5"> <Input placeholder="Ülke Yazınız" label="Ülke" iconElement={<FaFlag />} register={register} name="country" rules={{ required: "Ülke alanını doldurmak zorunludur.", }} error={errors.country?.message} /> <Input placeholder="İl Yazınız" label="İl" iconElement={<FaFlag />} register={register} name="c" rules={{ required: "İl alanını doldurmak zorunludur.", }} error={errors.city?.message} /> </div> {...inputs} </form> </> ); }); AddressForm.displayName = "AddressForm"; export default AddressForm;
any reason why they have to be separate <form> elements? from the AddressForm example it doesn't look like it has to be separate <form> elements, and you could just
<form>
  <Tab ... />
  <Button type="submit">Submit</Button>
</form>
if you can unify them into a single <form>, you can just add an action or an onSubmit to that <form> which can access the data of the entire form.

if they must remain three separate forms, you must have states in the root UserTab component to control the values. the inputs then must be controlled instead of uncontrolled.
I will do what you say and return again thank you