Add or remove input fields dynamically with ReactJS
Today we will show you how to add or remove input fields dynamically with ReactJS. In a real project, sometimes you need to implement the dynamic form fields using React. So you will find the step by step instruction to create dynamic form.
Dynamically Adding Multiple Input Fields in React JS, How to implement a dynamic form with controlled components in React hooks, react native dynamically add input fields to form, add input field on click react, building a dynamic, controlled form with react, dynamically adding multiple input fields react, react add form field dynamically, react-dynamic-forms github, react dynamic form generation, react add component dynamically on click.
Checkout more articles on ReactJS
Here we will take an example, where we will display two input fields dynamically and also add two buttons to add and remove the fields.
Steps to implement dynamic input fields
1. Create react application
Let’s start by creating a simple react application with the help of the create-react-app. If you don’t know how to create a react application then refer to the link below.
2. Design the form
To design the form, we will add two inputs and two buttons into the form.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | import React, { useState } from "react"; function App() { const [inputList, setInputList] = useState([{ firstName: "", lastName: "" }]); return ( <div className="App"> <h3><a href="https://cluemediator.com">Clue Mediator</a></h3> {inputList.map((x, i) => { return ( <div className="box"> <input name="firstName" value={x.firstName} /> <input className="ml10" name="lastName" value={x.lastName} /> <div className="btn-box"> {inputList.length !== 1 && <button className="mr10">Remove</button>} {inputList.length - 1 === i && <button>Add</button>} </div> </div> ); })} <div style={{ marginTop: 20 }}>{JSON.stringify(inputList)}</div> </div> ); } export default App; |
Our form should look like below.
3. Implement logic to add/remove fields
Now it’s time to write the logic. We will have three methods like input change, add button click and remove button click.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | // handle input change const handleInputChange = (e, index) => { const { name, value } = e.target; const list = [...inputList]; list[index][name] = value; setInputList(list); }; // handle click event of the Remove button const handleRemoveClick = index => { const list = [...inputList]; list.splice(index, 1); setInputList(list); }; // handle click event of the Add button const handleAddClick = () => { setInputList([...inputList, { firstName: "", lastName: "" }]); }; |
handleInputChange
– This method can be used on change of the input fields. In this method we need to update the value based on the given index.handleRemoveClick
– Here we will remove elements from the list based on the index.handleAddClick
– To add the new element in the list we have to call this method.
Let’s bind these methods with elements.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | return ( <div className="App"> <h3><a href="https://cluemediator.com">Clue Mediator</a></h3> {inputList.map((x, i) => { return ( <div className="box"> <input name="firstName" placeholder="Enter First Name" value={x.firstName} onChange={e => handleInputChange(e, i)} /> <input className="ml10" name="lastName" placeholder="Enter Last Name" value={x.lastName} onChange={e => handleInputChange(e, i)} /> <div className="btn-box"> {inputList.length !== 1 && <button className="mr10" onClick={() => handleRemoveClick(i)}>Remove</button>} {inputList.length - 1 === i && <button onClick={handleAddClick}>Add</button>} </div> </div> ); })} <div style={{ marginTop: 20 }}>{JSON.stringify(inputList)}</div> </div> ); |
Write the above code together in one file and check the output.
App.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | import React, { useState } from "react"; function App() { const [inputList, setInputList] = useState([{ firstName: "", lastName: "" }]); // handle input change const handleInputChange = (e, index) => { const { name, value } = e.target; const list = [...inputList]; list[index][name] = value; setInputList(list); }; // handle click event of the Remove button const handleRemoveClick = index => { const list = [...inputList]; list.splice(index, 1); setInputList(list); }; // handle click event of the Add button const handleAddClick = () => { setInputList([...inputList, { firstName: "", lastName: "" }]); }; return ( <div className="App"> <h3><a href="https://cluemediator.com">Clue Mediator</a></h3> {inputList.map((x, i) => { return ( <div className="box"> <input name="firstName" placeholder="Enter First Name" value={x.firstName} onChange={e => handleInputChange(e, i)} /> <input className="ml10" name="lastName" placeholder="Enter Last Name" value={x.lastName} onChange={e => handleInputChange(e, i)} /> <div className="btn-box"> {inputList.length !== 1 && <button className="mr10" onClick={() => handleRemoveClick(i)}>Remove</button>} {inputList.length - 1 === i && <button onClick={handleAddClick}>Add</button>} </div> </div> ); })} <div style={{ marginTop: 20 }}>{JSON.stringify(inputList)}</div> </div> ); } export default App; |
4. Output
That’s it for today.
Thank you for reading. Happy Coding!
Really great dynamic form but i want to ask what i have to update or edit the data passed in by the form, how do i display it with the number of dynamic input that the data was first created with in the first place.
Hi Emmanuel,
We are glad you liked it.
We are a little bit confused about your query. Can you please elaborate on it?
Subscribe us for weekly updates or like and follow us for regular updates.
I used the form to pass in data into my database but i would also like to edit the said data using the same form. now if i have multiple dynamic input data to display how would i do it.
Hello Emmanuel,
In the edit mode, you have to simply set the value of the
inputList
state variable in the same data structure.Suppose, if you have added dynamic input data (i.e. 3 records) into the database then use the same 3 records to assign into the
inputList
while performing the edit operation.Like, your
inputList
should be the same as the below in edit mode and the dynamic form will automatically render in DOM.[
{ "firstName":"John", "lastName":"Martin" },
{ "firstName":"Michael", "lastName":"Smith" },
{ "firstName":"James", "lastName":"Palmer" }
]
I Hope, your doubts will be clear now.
Let us know if you have any queries.
Awesome solution but what if there are not text input but have drop-down. Then how we handle it and how will populate data. E.g.
1Drop-down , 2 drop-down, 3 p-tag(but have to save value in state) , 4th drop-down.
On the base of 2nd(dd) 3-4 show and hide. And in 3-4, there can be any type of inputs or single value.
I was trying like that and it was not working.
Hi Vivek,
Can you please share your example using the StackBlitz link? We will be happy to help you!
Hi, Great explanation.. Thanks.. It would be great to know, is there a way to add ref’s to these dynamic input so that i can focus when the input box is added..?
Hi Dinesh,
You can use the same
inputList
variable to manage the input reference and use hooks to set focus after rendering the page.Let me know if you find any difficulties.
Subscribe us for weekly updates or like and follow us for regular updates.
Hi, I am to new react, so unable to contemplate using the inputList variable along with useRef hook.. is it possible to show a little example. It would be of great help..! Thanks
We will create a separate article for you and publish it in the next two days.
Stay connected with us.
Subscribe us for weekly updates or like and follow us for regular updates.
Sure..Thanks a lot!
Check out your requested article: Set focus on the dynamic input field in React
Very good! Congratulations! =)
Thanks a lot. No explanation could be better than this. such a great work.
Thank you so much Zatin, stay connected with us.
Subscribe us for weekly updates or like and follow us for regular updates.
Thank you for a great post. I have a question tho
const list = […inputList];
list[index][name] = value;
console.log(list[0] === inputList[0]) -> true
Since […inputList] is a shallow copy of inputList,
isn’t this changing the state directly without hook like setState?
In this case, it will also update the state variable because we are not doing the deep clone (For deep clone we can use the lodash library or use some other method). But I will suggest you to use the setState to rerender the DOM elements.
You are a god send. Thank you so much.
We are glad it helped!
Subscribe us for weekly updates or like and follow us for regular updates.
Hi
Really good example. Thanks for the post.
I am very new in react. I tried to add a dropdown selection input with other inputs. Unfortunately, it didn’t work. In my case, it failed to get the value of the selected item. Have you tried that?
You can use the dropdown element the same as an input field. The following link will help you to implement dropdown.
Subscribe us for weekly updates or like and follow us for regular updates.
Hello! very good example for people like me that are learning React, like Aman I’ve been trying to adapt the this tutorial but with dropdown elements that have mapped options from another list(each option value is ”codSede” and each option label is ”sede”) :
let sedesList = [
{ codSede: 1, sede: “Claustro” },
{ codSede: 2, sede: “Molinos” },
{ codSede: 3, sede: “Ciudad Torre Uno” },
]
, the goal is to change the state of inputList fields:
const [inputList, setInputList] = useState([{ codSede: 0, sede: “” }])
for the value and name of the selected option in each dropdown, but I havent had any luck so far, any suggestions would be greatly appreciated.
Again thanks for the awesome tutorial
Hi Andres,
Can you please share a CodePen or StackBlitz sample? So we can help you.
Thank you for answering! here is the link
https://stackblitz.com/edit/react-crxfu4?file=src/App.js
The onChange of the Select should trigger handleInputChange and add the values of the option to the state of inputList, ie the value of the first dropdown changes the value of the first object of inputList, the second dropdown, the second object etc..
Hi Andres,
Sorry for the delay, Here we have fixed your issues. Please check it out and let us know if you are facing any further issues.
Working Demo:
https://stackblitz.com/edit/react-ktvzwa
Hope this will help!
It works! thank you for the help!!
Hello, how I can use this code: const [inputList, setInputList] = useState([{ firstName: “”, lastName: “” }]); without useState? Because I used old react. Thanks
Hi Mike,
You have to declare your state variable like this…
// state variable
this.state = {
inputList: [{ firstName: "", lastName: "" }]
};
// change event
const { name, value } = e.target;
const list = [...inputList];
list[index][name] = value;
this.setState({ inputList: list });
Thanks. How I can use or change setInputList(list) ?
For example:
const handleRemoveClick = index => {
const list = […inputList];
list.splice(index, 1);
setInputList(list);
};
const handleAddClick = () => {
setInputList([…inputList, { firstName: “”, lastName: “” }]);
};
Use it like this…
const handleRemoveClick = index => {
const list = [...this.state.inputList];
list.splice(index, 1);
this.setState({ inputList: list });
};
const handleAddClick = () => {
this.setState({ inputList: [...this.state.inputList, { firstName: "", lastName: "" }] });
};
I have error:
Violation: Video.render(): A valid ReactComponent must be returned. You may have returned undefined, an array or some other invalid object.
my render
render: function() {
{
this.state.inputList.map((x, i) => {
return (
handleInputChange(e, i)}
/>
handleInputChange(e, i)}
/>
{this.state.inputList.length !== 1 && handleRemoveClick(i)}>Remove}
{this.state.inputList.length – 1 === i && Add}
);
})
}
}
Hi. Parse error: this.setState({ inputList: […this.state.inputList, { firstName: “”, lastName: “” }] });
here error […this.state.inputList, { firstName: “”, lastName: “” }]
Can you please provide me a Stackblitz or Codepen link so I can help you more?
A default input appears, how could we make no input appear by default? Thanks!!
Set an empty array in the
useState
as an initial state.First of all, the tutorials you provide are excellent, short and concise.
Regarding this it’s working, but adding a new input doesn’t seem to work properly instead it is just copying the value in all the array of the object.
I setup a Stackblitz for you to understand better: https://stackblitz.com/edit/react-dm6jwd?file=src%2FApp.js
I hope you can help me !:)
Thank you anyway!
Your Add button click logic is wrong. Please try to update it as below.
setinstance([...instance, { Country: "", Answer: "" }]);
I Hope, This will work for you!
thanks for a great tutorial, I want to ask something
what if we want to add different types of the input field like image and text dynamically, we have more than one type of add button so we can add the next input by choice it can be image or text or heading like you created this page in the different post you add different no. of images different no. text and heading dynamically
please ans me
Hi Sandeep, You can add any number of the field. You have to simply manage it as an input field. If you are adding an image then you can use image src in the array.
Interesting approach! How would you apply this to a WordPress Gutenberg block?
Nevermind. I figured out.
Here, you can share your solution with other visitors.
Hi..great article!!!
I am having an issue on handleRemoveClick()
The ‘list’ is getting updated but in setInputList(list) not setting the updated values.
setInputList(list) – is one step behind (It is updated in the next remove click)
why is this happening and how can i solve it?
Thanks in advance.
Hi Sucheta,
You can not setState is an asynchronous method. So you can not immediately get the updated result in the next execution. Please try to compare your code with GitHub or StackBlitz demo. You will find the source link at the end of the article.
This is really excellent, thanks. I am trying to impliment it with React Hook Form and not getting very far. Any change of a new tutorial with React Hook Form? 🙂
Sure, we’ll write the article on the React Hook Form.
Thank you!
Hi there,
I tried to add a submit button at the bottom and log the inputList but i am getting the error : “TypeError: Cannot read property ‘projectType’ of null”.
Can advise me on what i am doing wrong?
Thanks.
Hi Taha,
Make sure you should have a value in object/array before reading the property ‘projectType’. Is it possible to share your code via StackBlitz? You can also compare your code with GitHub/StackBlitz code.
That is really nice of you to share your experience.
helped me ,
Thank you very much
Thanks for best article. But I get eslint error – use callback in setState when referencing the previous state – in code const list = […this.state.inputList]; please guide
Thanks!
Can you please share the error?
Hello, how I can use this code as const [winningTiers, setWinningTiers] = useState([{tier_wallet_type: “”, rank_from: “”, rank_to: “”, distribution: “”}])
rank_from: 1 , rank_to: 1
rank_from: 2, rank_to: 10
rank_from: 11, rank_to: 50
i just want to update the input value greater then previous rank. kindly do the needful.
Are you trying to add validation?
I have shared the details info in the email please check
Replied
hello, i have a problem with the event handler when i make the eventHandler always error Element implicitly has an ‘any’ type because expression of type ‘any’ can’t be used to index type ‘{ name: string; email: string; }’ like this