forevereffort
forevereffort

Reputation: 462

What is the professional way to manage lots of form input fields in ReactJS?

My React App has over 20 fields on form tag. and my working code like the following

function DriverForm() {
    const [formData1, setFormData1] = useState(1);
    const [formData2, setFormData2] = useState(2);
    const [formData3, setFormData3] = useState(3);
    const [formData4, setFormData4] = useState(4);
    const [formData5, setFormData5] = useState(5);

    const handleSubmit = (event) => {
        event.preventDefault();
    };

    return (
        <div className="wrapper">
            <form onSubmit={handleSubmit}>
                <input value={formData1} onChange={(e) => setFormData1(e.target.value)} />
                <input value={formData2} onChange={(e) => setFormData2(e.target.value)} />
                <input value={formData3} onChange={(e) => setFormData3(e.target.value)} />
                <input value={formData4} onChange={(e) => setFormData4(e.target.value)} />
                <input value={formData5} onChange={(e) => setFormData5(e.target.value)} />
                <button type="submit">Submit</button>
            </form>
        </div>
    );
}

as you see, my code has the code repeat to declare the input field state variable like const [formData5, setFormData5] = useState(5); and At the rendering function, onChange={(e) => setFormData1(e.target.value)} was repeated lots of time.

is there any way to be simple and look professional by using json object and other?

Upvotes: 2

Views: 1791

Answers (4)

Subrato Pattanaik
Subrato Pattanaik

Reputation: 6059

Working with forms in react is one of the most challenging problems to solve when developing applications. The best way to work with the form is react-hook-form. It is introduced so that the performance or latency of the react application will be improved to such a great extend. There is another way of creating a form in react is Formik.
Both Formik and React Hook Form are solving the same problem (provides a way to store form data in local state), but React Hook Form is a way of creating a form with uncontrolled components and the hooks allow it to give a better performance result than Formik.

I'll give you one simple example of react-hook-form.

import React, {useState} from "react";
import { useForm } from "react-hook-form";

function App() {
  const { register, handleSubmit } = useForm();
  const {data, setData} = useState({});
  const onSubmit = (formData) => {
     console.log(formData); // an object of form Data
     setData(formData);
  }   
  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input name="formInput1" ref={register} />
      <input name="formInput2" ref={register} />
      <input type="submit" />
    </form>
  );
}

When we console log the form data we get an object of form input.

>console

object{
 formInput1: "your value",
 formInput2: "your 2nd value"
}

You can store this object in a local state or in a database through API call.

I'll recommend you to learn both Formik and React hook form then you will be able to differentiate between them. Yes, react-hook-form is the best way to create a form in react in terms of performance. Formik lets you easy to understand and create a form in one go.

Others have given the best example of creating a react form without using formik and react hook form.

Upvotes: 1

Benjamin
Benjamin

Reputation: 3656

There are many answers to this question. However, one of the rules I like to code by is 'Everything is an array'.

I would start by creating an array of form fields. Then take those form fields, and build the initial state object to be used in the formData state hook.

const formFields = [
  { name: 'field1', type: 'text', initialValue: '1' },
  { name: 'field2', type: 'text', initialValue: '2' },
  { name: 'field3', type: 'text', initialValue: '3' },
  { name: 'field4', type: 'text', initialValue: '4' },
  { name: 'field5', type: 'text', initialValue: '5' },
];

const initalState = formFields.reduce(
  (acc, next) => ({ ...acc, [next.name]: next.initalValue }),
  {}
);

Then create a single handleChange handler.

const handleChange = (name, value) => {
  setFormData({
    ...formData,
    [name]: value,
  });
};

And finally, map the formFields in your render function.

{formFields.map(({ name, type }) => (
  <input
    key={name}
    name={name}
    type={type}
    value={formData[name]}
    onChange={(e) => handleChange(e.target.value, name)}
  />
))}

Complete code:

const formFields = [
  { name: 'field1', type: 'text', initialValue: '1' },
  { name: 'field2', type: 'text', initialValue: '2' },
  { name: 'field3', type: 'text', initialValue: '3' },
  { name: 'field4', type: 'text', initialValue: '4' },
  { name: 'field5', type: 'text', initialValue: '5' },
];

const initalState = formFields.reduce(
  (acc, next) => ({ ...acc, [next.name]: next.initalValue }),
  {}
);

function DriverForm() {
  const [formData, setFormData] = useState(initalState);

  const handleChange = (name, value) => {
    setFormData({
      ...formData,
      [name]: value,
    });
  };

  const handleSubmit = (event) => {
    event.preventDefault();
  };

  return (
    <div className="wrapper">
      <form onSubmit={handleSubmit}>
        {formFields.map(({ name, type }) => (
          <input
            key={name}
            name={name}
            type={type}
            value={formData[name]}
            onChange={(e) => handleChange(e.target.value, name)}
          />
        ))}
        <button type="submit">Submit</button>
      </form>
    </div>
  );
}

Upvotes: 4

Drew Reese
Drew Reese

Reputation: 203427

I suppose you could make the code more DRY by combining the duplicated bits.

  1. Single state object holding field values by input name
  2. Single change handler to handle merging in state updates
  3. Assign inputs a name attribute to be passed with change event

DRY solution

function DriverForm() {
  const [formData, setFormData] = useState({
    data1: 1,
    data2: 2,
    // etc...
  });

  const handleSubmit = (event) => {
    event.preventDefault();
    // handle formData
  };

  const handleChange = event => {
    event.preventDefault();
    const { name, value } = event.target;
    setFormData(formData => ({
      ...formData,
      [name]: value,
    }))
  }

  return (
    <div className="wrapper">
      <form onSubmit={handleSubmit}>
        <input value={formData.data1} name="data1" onChange={handleChange} />
        <input value={formData.data2} name="data2" onChange={handleChange} />        
        // etc..
        <button type="submit">Submit</button>
      </form>
    </div>
  );
}

If you know ahead of time what the input types will be you can load them into a configuration array and map them

const fieldData = [
  {
    name: 'data1',
    type: 'text',
  },
  // etc...
];

...

<form onSubmit={handleSubmit}>
  {fieldData.map(({ name, type }) => (
    <input
      key={name{
      type={type}
      value={formData[name]}
      name={name}
      onChange={handleChange}
    />
  ))}
  <button type="submit">Submit</button>
</form>

Upvotes: 6

Gayatri Dipali
Gayatri Dipali

Reputation: 1283

import React, { useState } from 'react'

const App=()=>{

    const[fullname, setFullName]=useState({
        fname:"",
        lname:"",
        email:"",
        phone:""
    }); 

    const inputEvent=(event)=>{
        // const value = event.target.value;
        // const name = event.target.name;
        const {name,value}=event.target;

        setFullName((preValue)=>{
            console.log(preValue)
            console.log(value)
            return{
                ...preValue,//gets the previous value
                [name]:value//sets the value to the field that is getting changed
            }
        })
    }

    const submits=(event)=>{
        event.preventDefault();
        alert('Form has been submitted')
    }
return(
    <>
    <div>
    <form onSubmit={submits}>
    <div>
    <h1>Hello {fullname.fname} {fullname.lname}</h1>
    <div className='container'>
    <p>{fullname.email}</p>
    </div>
    {/* <p>{fullname.phone}</p> */}
    <input type='text' 
    placeholder='Enter Your Name'
    onChange={inputEvent}
    name='fname'
    value={fullname.fname}
     />
    <input type='text' 
    placeholder='Enter Your Last Name'
    onChange={inputEvent}
    name='lname'
    value={fullname.lname}
     /> 
    <input type='text' 
    placeholder='Enter Your Email'
    onChange={inputEvent}
    name='email'
    value={fullname.email}
     /> 
    <input type='phone' 
    placeholder='Enter Your Phone Number'
    onChange={inputEvent}
    name='phone'
    value={fullname.phone}
     /> 
    <button type='submit'>Submit</button>
    </div>
    </form>
    </div>
    </>
)
};

export default App;

This how handle too much of inputs in a form you can extend it in your desired way

What you should do is just replace the names and values in your way like formData1

Upvotes: 0

Related Questions