Reputation: 462
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
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
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)}
/>
))}
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
Reputation: 203427
I suppose you could make the code more DRY by combining the duplicated bits.
name
attribute to be passed with change eventDRY 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
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